contribute-now 0.6.0 → 0.6.1-dev.4075d32

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 +145 -89
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -293,6 +293,12 @@ async function getCommitHash(ref) {
293
293
  return null;
294
294
  return stdout.trim() || null;
295
295
  }
296
+ async function getCommitSubject(ref) {
297
+ const { exitCode, stdout } = await run(["log", "-1", "--format=%s", ref]);
298
+ if (exitCode !== 0)
299
+ return null;
300
+ return stdout.trim() || null;
301
+ }
296
302
  async function determineRebaseStrategy(currentBranch, syncRef) {
297
303
  const upstreamRef = await getUpstreamRef();
298
304
  if (!upstreamRef) {
@@ -664,21 +670,21 @@ LogEngine.configure({
664
670
  mode: LogMode.INFO,
665
671
  format: {
666
672
  includeIsoTimestamp: false,
667
- includeLocalTime: true,
673
+ includeLocalTime: false,
668
674
  includeEmoji: true
669
675
  }
670
676
  });
671
- function success(msg) {
672
- LogEngine.log(msg);
677
+ function success(msg, emoji = "✅") {
678
+ LogEngine.log(msg, undefined, { emoji });
673
679
  }
674
- function error(msg) {
675
- LogEngine.error(msg);
680
+ function error(msg, emoji = "\uD83D\uDEA8") {
681
+ LogEngine.error(msg, undefined, { emoji });
676
682
  }
677
- function warn(msg) {
678
- LogEngine.warn(msg);
683
+ function warn(msg, emoji = "⚠️") {
684
+ LogEngine.warn(msg, undefined, { emoji });
679
685
  }
680
- function info(msg) {
681
- LogEngine.info(msg);
686
+ function info(msg, emoji = "ℹ️") {
687
+ LogEngine.info(msg, undefined, { emoji });
682
688
  }
683
689
  function heading(msg) {
684
690
  console.log(`
@@ -1677,8 +1683,8 @@ async function handleCurrentBranchDeletion(currentBranch, baseBranch, config) {
1677
1683
  if (rebaseResult.exitCode !== 0) {
1678
1684
  await rebaseAbort();
1679
1685
  warn("Rebase had conflicts — aborted to keep the repo in a clean state.");
1680
- info(`Your work is saved on ${pc5.bold(newBranchName)}. After cleanup, rebase manually:`);
1681
- info(` ${pc5.bold(`git checkout ${newBranchName} && git rebase ${syncSource2.ref}`)}`);
1686
+ info(`Your work is saved on ${pc5.bold(newBranchName)}. After cleanup, rebase manually:`, "");
1687
+ info(` ${pc5.bold(`git checkout ${newBranchName} && git rebase ${syncSource2.ref}`)}`, "");
1682
1688
  } else {
1683
1689
  success(`Rebased ${pc5.bold(newBranchName)} onto ${pc5.bold(syncSource2.ref)}.`);
1684
1690
  }
@@ -1753,7 +1759,7 @@ var clean_default = defineCommand2({
1753
1759
  const mergedPR = await getMergedPRForBranch(currentBranch);
1754
1760
  if (mergedPR) {
1755
1761
  warn(`PR #${mergedPR.number} (${pc5.bold(mergedPR.title)}) has already been merged.`);
1756
- info(`Link: ${pc5.underline(mergedPR.url)}`);
1762
+ info(`Link: ${pc5.underline(mergedPR.url)}`, "");
1757
1763
  goneCandidates.push(currentBranch);
1758
1764
  }
1759
1765
  }
@@ -1827,7 +1833,7 @@ ${pc5.bold("Stale branches (remote deleted, likely squash-merged):")}`);
1827
1833
  }
1828
1834
  }
1829
1835
  if (mergedCandidates.length === 0 && goneCandidates.length === 0) {
1830
- info("No branches to clean up. Everything is tidy! \uD83E\uDDF9");
1836
+ info("No branches to clean up. Everything is tidy!", "\uD83E\uDDF9");
1831
1837
  }
1832
1838
  const finalBranch = await getCurrentBranch();
1833
1839
  if (finalBranch && protectedBranches.has(finalBranch)) {
@@ -2069,7 +2075,7 @@ ${pc6.bold("Changed files:")}`);
2069
2075
  error(`Failed to commit: ${result.stderr}`);
2070
2076
  process.exit(1);
2071
2077
  }
2072
- success(`✅ Committed: ${pc6.bold(finalMessage)}`);
2078
+ success(`Committed: ${pc6.bold(finalMessage)}`);
2073
2079
  }
2074
2080
  });
2075
2081
  async function runGroupCommit(model, config) {
@@ -2176,7 +2182,7 @@ ${pc6.bold(`AI suggested ${validGroups.length} commit group(s):`)}
2176
2182
  continue;
2177
2183
  }
2178
2184
  committed++;
2179
- success(`✅ Committed group ${i + 1}: ${pc6.bold(group.message)}`);
2185
+ success(`Committed group ${i + 1}: ${pc6.bold(group.message)}`);
2180
2186
  }
2181
2187
  } else {
2182
2188
  for (let i = 0;i < validGroups.length; i++) {
@@ -2247,7 +2253,7 @@ ${pc6.bold(`AI suggested ${validGroups.length} commit group(s):`)}
2247
2253
  continue;
2248
2254
  }
2249
2255
  committed++;
2250
- success(`✅ Committed group ${i + 1}: ${pc6.bold(message)}`);
2256
+ success(`Committed group ${i + 1}: ${pc6.bold(message)}`);
2251
2257
  actionDone = true;
2252
2258
  }
2253
2259
  }
@@ -2255,8 +2261,8 @@ ${pc6.bold(`AI suggested ${validGroups.length} commit group(s):`)}
2255
2261
  if (committed === 0) {
2256
2262
  warn("No groups were committed.");
2257
2263
  } else {
2258
- success(`
2259
- \uD83C\uDF89 ${committed} of ${validGroups.length} group(s) committed successfully.`);
2264
+ console.log();
2265
+ success(`${committed} of ${validGroups.length} group(s) committed successfully.`, "\uD83C\uDF89");
2260
2266
  }
2261
2267
  process.exit(0);
2262
2268
  }
@@ -2268,7 +2274,7 @@ import pc7 from "picocolors";
2268
2274
  // package.json
2269
2275
  var package_default = {
2270
2276
  name: "contribute-now",
2271
- version: "0.6.0",
2277
+ version: "0.6.1-dev.4075d32",
2272
2278
  description: "Developer CLI that automates git workflows — branching, syncing, committing, and PRs — with multi-workflow and commit convention support.",
2273
2279
  type: "module",
2274
2280
  bin: {
@@ -2731,7 +2737,7 @@ async function installHook() {
2731
2737
  }
2732
2738
  if (config.commitConvention === "none") {
2733
2739
  warn('Commit convention is set to "none". No hook to install.');
2734
- info("Change your convention with `contrib setup` first.");
2740
+ info("Change your convention with `contrib setup` first.", "");
2735
2741
  process.exit(0);
2736
2742
  }
2737
2743
  const hookPath = getHookPath();
@@ -2751,8 +2757,8 @@ async function installHook() {
2751
2757
  }
2752
2758
  writeFileSync2(hookPath, generateHookScript(), { mode: 493 });
2753
2759
  success(`commit-msg hook installed.`);
2754
- info(`Convention: ${pc8.bold(CONVENTION_LABELS[config.commitConvention])}`);
2755
- info(`Path: ${pc8.dim(hookPath)}`);
2760
+ info(`Convention: ${pc8.bold(CONVENTION_LABELS[config.commitConvention])}`, "");
2761
+ info(`Path: ${pc8.dim(hookPath)}`, "");
2756
2762
  warn("Note: hooks can be bypassed with `git commit --no-verify`.");
2757
2763
  }
2758
2764
  async function uninstallHook() {
@@ -3169,7 +3175,7 @@ async function handleSave(message) {
3169
3175
  return;
3170
3176
  }
3171
3177
  success(`Saved: ${pc10.dim(label)}`);
3172
- info(`Use ${pc10.bold("contrib save --restore")} to bring them back.`);
3178
+ info(`Use ${pc10.bold("contrib save --restore")} to bring them back.`, "");
3173
3179
  }
3174
3180
  async function handleRestore() {
3175
3181
  heading("\uD83D\uDCBE contrib save --restore");
@@ -3214,8 +3220,8 @@ async function handleList() {
3214
3220
  console.log(` ${idx} ${msg}`);
3215
3221
  }
3216
3222
  console.log();
3217
- info(`Use ${pc10.bold("contrib save --restore")} to bring changes back.`);
3218
- info(`Use ${pc10.bold("contrib save --drop")} to discard saved changes.`);
3223
+ info(`Use ${pc10.bold("contrib save --restore")} to bring changes back.`, "");
3224
+ info(`Use ${pc10.bold("contrib save --drop")} to discard saved changes.`, "");
3219
3225
  }
3220
3226
  async function handleDrop() {
3221
3227
  heading("\uD83D\uDCBE contrib save --drop");
@@ -3425,7 +3431,7 @@ var setup_default = defineCommand8({
3425
3431
  success(`Added remote ${pc11.bold(upstreamRemote)} → ${upstreamUrl}`);
3426
3432
  } else {
3427
3433
  error("An upstream remote URL is required for contributors.");
3428
- info("Add it manually: git remote add upstream <url>");
3434
+ info("Add it manually: git remote add upstream <url>", "");
3429
3435
  process.exit(1);
3430
3436
  }
3431
3437
  }
@@ -3441,9 +3447,9 @@ var setup_default = defineCommand8({
3441
3447
  commitConvention
3442
3448
  };
3443
3449
  writeConfig(config);
3444
- success(`✅ Config written to .contributerc.json`);
3450
+ success(`Config written to .contributerc.json`);
3445
3451
  const syncRemote = config.role === "contributor" ? config.upstream : config.origin;
3446
- info(`Fetching ${pc11.bold(syncRemote)} to verify branch configuration...`);
3452
+ info(`Fetching ${pc11.bold(syncRemote)} to verify branch configuration...`, "");
3447
3453
  await fetchRemote(syncRemote);
3448
3454
  const mainRef = `${syncRemote}/${config.mainBranch}`;
3449
3455
  if (!await refExists(mainRef)) {
@@ -3565,7 +3571,7 @@ var start_default = defineCommand9({
3565
3571
  info(`Creating branch: ${pc12.bold(branchName)}`);
3566
3572
  if (await branchExists(branchName)) {
3567
3573
  error(`Branch ${pc12.bold(branchName)} already exists.`);
3568
- info(` Use ${pc12.bold(`git checkout ${branchName}`)} to switch to it, or choose a different name.`);
3574
+ info(` Use ${pc12.bold(`git checkout ${branchName}`)} to switch to it, or choose a different name.`, "");
3569
3575
  process.exit(1);
3570
3576
  }
3571
3577
  await fetchRemote(syncSource.remote);
@@ -3593,11 +3599,11 @@ var start_default = defineCommand9({
3593
3599
  error(`Failed to create branch: ${result2.stderr}`);
3594
3600
  process.exit(1);
3595
3601
  }
3596
- success(`✅ Created ${pc12.bold(branchName)} from ${pc12.bold(syncSource.ref)}`);
3602
+ success(`Created ${pc12.bold(branchName)} from ${pc12.bold(syncSource.ref)}`);
3597
3603
  return;
3598
3604
  }
3599
3605
  error(`Failed to update ${pc12.bold(baseBranch)}: ${updateResult.stderr}`);
3600
- info("Make sure your base branch exists locally or the remote ref is available.");
3606
+ info("Make sure your base branch exists locally or the remote ref is available.", "");
3601
3607
  process.exit(1);
3602
3608
  }
3603
3609
  const result = await createBranch(branchName, baseBranch);
@@ -3605,7 +3611,7 @@ var start_default = defineCommand9({
3605
3611
  error(`Failed to create branch: ${result.stderr}`);
3606
3612
  process.exit(1);
3607
3613
  }
3608
- success(`✅ Created ${pc12.bold(branchName)} from latest ${pc12.bold(baseBranch)}`);
3614
+ success(`Created ${pc12.bold(branchName)} from latest ${pc12.bold(baseBranch)}`);
3609
3615
  }
3610
3616
  });
3611
3617
 
@@ -3668,6 +3674,51 @@ var status_default = defineCommand10({
3668
3674
  } else if (currentBranch) {
3669
3675
  console.log(pc13.dim(` (on ${pc13.bold(currentBranch)} branch)`));
3670
3676
  }
3677
+ let branchesAligned = true;
3678
+ {
3679
+ const alignRefs = [];
3680
+ const devRemote = isContributor ? upstream : origin;
3681
+ const hashResults = await Promise.all([
3682
+ getCommitHash(mainBranch).then((h) => ({ name: mainBranch, hash: h })),
3683
+ getCommitHash(`${origin}/${mainBranch}`).then((h) => ({ name: `${origin}/${mainBranch}`, hash: h })),
3684
+ ...hasDevBranch(workflow) && config.devBranch ? [
3685
+ getCommitHash(config.devBranch).then((h) => ({ name: config.devBranch, hash: h })),
3686
+ getCommitHash(`${devRemote}/${config.devBranch}`).then((h) => ({
3687
+ name: `${devRemote}/${config.devBranch}`,
3688
+ hash: h
3689
+ }))
3690
+ ] : []
3691
+ ]);
3692
+ for (const { name, hash } of hashResults) {
3693
+ if (hash)
3694
+ alignRefs.push({ name, hash });
3695
+ }
3696
+ if (alignRefs.length > 1) {
3697
+ const groups = new Map;
3698
+ for (const { name, hash } of alignRefs) {
3699
+ if (!groups.has(hash))
3700
+ groups.set(hash, []);
3701
+ groups.get(hash).push(name);
3702
+ }
3703
+ branchesAligned = groups.size === 1;
3704
+ console.log();
3705
+ console.log(` ${pc13.bold("\uD83D\uDD17 Branch Alignment")}`);
3706
+ for (const [hash, names] of groups) {
3707
+ const short = hash.slice(0, 7);
3708
+ const nameStr = names.map((n) => pc13.bold(n)).join(pc13.dim(" · "));
3709
+ console.log(` ${pc13.yellow(short)} ${pc13.dim("──")} ${nameStr}`);
3710
+ const subject = await getCommitSubject(hash);
3711
+ if (subject) {
3712
+ console.log(` ${pc13.dim(subject)}`);
3713
+ }
3714
+ }
3715
+ if (branchesAligned) {
3716
+ console.log(` ${pc13.green("✓")} ${pc13.green("All branches aligned")} ${pc13.dim("— ready to start")}`);
3717
+ } else {
3718
+ console.log(` ${pc13.yellow("⚠")} ${pc13.yellow("Branches are not fully aligned")}`);
3719
+ }
3720
+ }
3721
+ }
3671
3722
  const hasFiles = fileStatus.staged.length > 0 || fileStatus.modified.length > 0 || fileStatus.untracked.length > 0;
3672
3723
  if (hasFiles) {
3673
3724
  console.log();
@@ -3693,6 +3744,9 @@ var status_default = defineCommand10({
3693
3744
  console.log(` ${pc13.green("✓")} ${pc13.dim("Working tree clean")}`);
3694
3745
  }
3695
3746
  const tips = [];
3747
+ if (!branchesAligned) {
3748
+ tips.push(`Run ${pc13.bold("contrib sync")} to align your local branches with the remote`);
3749
+ }
3696
3750
  if (fileStatus.staged.length > 0) {
3697
3751
  tips.push(`Run ${pc13.bold("contrib commit")} to commit staged changes`);
3698
3752
  }
@@ -3870,8 +3924,8 @@ async function performSquashMerge(origin, baseBranch, featureBranch, options) {
3870
3924
  warn(`Could not delete remote branch: ${delRemote.stderr.trim()}`);
3871
3925
  }
3872
3926
  }
3873
- success(`✅ Squash merged ${pc14.bold(featureBranch)} into ${pc14.bold(baseBranch)} and pushed.`);
3874
- info(`Run ${pc14.bold("contrib start")} to begin a new feature.`);
3927
+ success(`Squash merged ${pc14.bold(featureBranch)} into ${pc14.bold(baseBranch)} and pushed.`);
3928
+ info(`Run ${pc14.bold("contrib start")} to begin a new feature.`, "");
3875
3929
  }
3876
3930
  var submit_default = defineCommand11({
3877
3931
  meta: {
@@ -3924,7 +3978,7 @@ var submit_default = defineCommand11({
3924
3978
  const hasAnything = hasCommits || dirty;
3925
3979
  if (!hasAnything) {
3926
3980
  error("No local changes or commits to move. Switch to a feature branch first.");
3927
- info(` Run ${pc14.bold("contrib start")} to create a new feature branch.`);
3981
+ info(` Run ${pc14.bold("contrib start")} to create a new feature branch.`, "");
3928
3982
  process.exit(1);
3929
3983
  }
3930
3984
  if (hasCommits) {
@@ -3983,10 +4037,10 @@ var submit_default = defineCommand11({
3983
4037
  }
3984
4038
  success(`Created ${pc14.bold(newBranchName)} with your changes.`);
3985
4039
  await updateLocalBranch(currentBranch, remoteRef);
3986
- info(`Reset ${pc14.bold(currentBranch)} back to ${pc14.bold(remoteRef)} — no damage done.`);
4040
+ info(`Reset ${pc14.bold(currentBranch)} back to ${pc14.bold(remoteRef)} — no damage done.`, "");
3987
4041
  console.log();
3988
4042
  success(`You're now on ${pc14.bold(newBranchName)} with all your work intact.`);
3989
- info(`Run ${pc14.bold("contrib submit")} again to push and create your PR.`);
4043
+ info(`Run ${pc14.bold("contrib submit")} again to push and create your PR.`, "");
3990
4044
  return;
3991
4045
  }
3992
4046
  heading("\uD83D\uDE80 contrib submit");
@@ -4064,11 +4118,11 @@ var submit_default = defineCommand11({
4064
4118
  }
4065
4119
  if (rebaseResult.exitCode !== 0) {
4066
4120
  warn("Rebase encountered conflicts. Resolve them manually, then run:");
4067
- info(` ${pc14.bold("git rebase --continue")}`);
4121
+ info(` ${pc14.bold("git rebase --continue")}`, "");
4068
4122
  } else {
4069
4123
  success(`Rebased ${pc14.bold(newBranchName)} onto ${pc14.bold(syncSource2.ref)}.`);
4070
4124
  }
4071
- info(`All your changes are preserved. Run ${pc14.bold("contrib submit")} when ready to create a new PR.`);
4125
+ info(`All your changes are preserved. Run ${pc14.bold("contrib submit")} when ready to create a new PR.`, "");
4072
4126
  return;
4073
4127
  }
4074
4128
  warn("Discarding local changes...");
@@ -4105,8 +4159,8 @@ var submit_default = defineCommand11({
4105
4159
  error(`Failed to push: ${pushResult2.stderr}`);
4106
4160
  if (pushResult2.stderr.includes("rejected") || pushResult2.stderr.includes("non-fast-forward")) {
4107
4161
  warn("The remote branch has diverged. Try:");
4108
- info(` git pull --rebase ${origin} ${currentBranch}`);
4109
- info(" Then run `contrib submit` again.");
4162
+ info(` git pull --rebase ${origin} ${currentBranch}`, "");
4163
+ info(" Then run `contrib submit` again.", "");
4110
4164
  }
4111
4165
  process.exit(1);
4112
4166
  }
@@ -4142,22 +4196,39 @@ ${pc14.dim("AI body preview:")}`);
4142
4196
  warn(`AI unavailable: ${copilotError}`);
4143
4197
  }
4144
4198
  }
4145
- if (!args["no-ai"]) {
4146
- await tryGenerateAI();
4147
- }
4148
4199
  const CANCEL = "Cancel";
4149
4200
  const SQUASH_LOCAL = `Squash merge to ${baseBranch} locally (no PR)`;
4150
4201
  const REGENERATE = "Regenerate AI description";
4151
4202
  let submitAction = "cancel";
4152
4203
  const isMaintainer = config.role === "maintainer";
4204
+ if (isMaintainer) {
4205
+ const maintainerChoice = await selectPrompt("How would you like to submit your changes?", ["Create a PR", SQUASH_LOCAL, CANCEL]);
4206
+ if (maintainerChoice === CANCEL) {
4207
+ warn("Submit cancelled.");
4208
+ return;
4209
+ }
4210
+ if (maintainerChoice === SQUASH_LOCAL) {
4211
+ await performSquashMerge(origin, baseBranch, currentBranch, {
4212
+ model: args.model,
4213
+ convention: config.commitConvention
4214
+ });
4215
+ return;
4216
+ }
4217
+ }
4218
+ if (!args["no-ai"]) {
4219
+ await tryGenerateAI();
4220
+ }
4153
4221
  let actionResolved = false;
4154
4222
  while (!actionResolved) {
4155
4223
  if (prTitle && prBody) {
4156
- const choices = ["Use AI description"];
4157
- if (isMaintainer)
4158
- choices.push(SQUASH_LOCAL);
4159
- choices.push("Edit title", "Write manually", "Use gh --fill (auto-fill from commits)", REGENERATE, CANCEL);
4160
- const action = await selectPrompt("What would you like to do with the PR description?", choices);
4224
+ const action = await selectPrompt("What would you like to do with the PR description?", [
4225
+ "Use AI description",
4226
+ "Edit title",
4227
+ "Write manually",
4228
+ "Use gh --fill (auto-fill from commits)",
4229
+ REGENERATE,
4230
+ CANCEL
4231
+ ]);
4161
4232
  if (action === CANCEL) {
4162
4233
  submitAction = "cancel";
4163
4234
  actionResolved = true;
@@ -4165,9 +4236,6 @@ ${pc14.dim("AI body preview:")}`);
4165
4236
  prTitle = null;
4166
4237
  prBody = null;
4167
4238
  await tryGenerateAI();
4168
- } else if (action === SQUASH_LOCAL) {
4169
- submitAction = "squash";
4170
- actionResolved = true;
4171
4239
  } else if (action === "Use AI description") {
4172
4240
  submitAction = "create-pr";
4173
4241
  actionResolved = true;
@@ -4186,8 +4254,6 @@ ${pc14.dim("AI body preview:")}`);
4186
4254
  }
4187
4255
  } else {
4188
4256
  const choices = [];
4189
- if (isMaintainer)
4190
- choices.push(SQUASH_LOCAL);
4191
4257
  if (!args["no-ai"])
4192
4258
  choices.push(REGENERATE);
4193
4259
  choices.push("Write title & body manually", "Use gh --fill (auto-fill from commits)", CANCEL);
@@ -4197,9 +4263,6 @@ ${pc14.dim("AI body preview:")}`);
4197
4263
  actionResolved = true;
4198
4264
  } else if (action === REGENERATE) {
4199
4265
  await tryGenerateAI();
4200
- } else if (action === SQUASH_LOCAL) {
4201
- submitAction = "squash";
4202
- actionResolved = true;
4203
4266
  } else if (action === "Write title & body manually") {
4204
4267
  prTitle = await inputPrompt("PR title");
4205
4268
  prBody = await inputPrompt("PR body (markdown)");
@@ -4215,23 +4278,16 @@ ${pc14.dim("AI body preview:")}`);
4215
4278
  warn("Submit cancelled.");
4216
4279
  return;
4217
4280
  }
4218
- if (submitAction === "squash") {
4219
- await performSquashMerge(origin, baseBranch, currentBranch, {
4220
- model: args.model,
4221
- convention: config.commitConvention
4222
- });
4223
- return;
4224
- }
4225
4281
  info(`Pushing ${pc14.bold(currentBranch)} to ${origin}...`);
4226
4282
  const pushResult = await pushSetUpstream(origin, currentBranch);
4227
4283
  if (pushResult.exitCode !== 0) {
4228
4284
  error(`Failed to push: ${pushResult.stderr}`);
4229
4285
  if (pushResult.stderr.includes("rejected") || pushResult.stderr.includes("non-fast-forward")) {
4230
4286
  warn("The remote branch has diverged. Try:");
4231
- info(` git pull --rebase ${origin} ${currentBranch}`);
4232
- info(" Then run `contrib submit` again.");
4233
- info("If you need to force push (use with caution):");
4234
- info(` git push --force-with-lease ${origin} ${currentBranch}`);
4287
+ info(` git pull --rebase ${origin} ${currentBranch}`, "");
4288
+ info(" Then run `contrib submit` again.", "");
4289
+ info("If you need to force push (use with caution):", "");
4290
+ info(` git push --force-with-lease ${origin} ${currentBranch}`, "");
4235
4291
  }
4236
4292
  process.exit(1);
4237
4293
  }
@@ -4240,10 +4296,10 @@ ${pc14.dim("AI body preview:")}`);
4240
4296
  if (repoInfo) {
4241
4297
  const prUrl = `https://github.com/${repoInfo.owner}/${repoInfo.repo}/compare/${baseBranch}...${currentBranch}?expand=1`;
4242
4298
  console.log();
4243
- info("Create your PR manually:");
4299
+ info("Create your PR manually:", "");
4244
4300
  console.log(` ${pc14.cyan(prUrl)}`);
4245
4301
  } else {
4246
- info("gh CLI not available. Create your PR manually on GitHub.");
4302
+ info("gh CLI not available. Create your PR manually on GitHub.", "");
4247
4303
  }
4248
4304
  return;
4249
4305
  }
@@ -4253,7 +4309,7 @@ ${pc14.dim("AI body preview:")}`);
4253
4309
  error(`Failed to create PR: ${fillResult.stderr}`);
4254
4310
  process.exit(1);
4255
4311
  }
4256
- success(`✅ PR created: ${fillResult.stdout.trim()}`);
4312
+ success(`PR created: ${fillResult.stdout.trim()}`);
4257
4313
  return;
4258
4314
  }
4259
4315
  if (!prTitle) {
@@ -4270,7 +4326,7 @@ ${pc14.dim("AI body preview:")}`);
4270
4326
  error(`Failed to create PR: ${prResult.stderr}`);
4271
4327
  process.exit(1);
4272
4328
  }
4273
- success(`✅ PR created: ${prResult.stdout.trim()}`);
4329
+ success(`PR created: ${prResult.stdout.trim()}`);
4274
4330
  }
4275
4331
  });
4276
4332
 
@@ -4360,8 +4416,8 @@ var switch_default = defineCommand12({
4360
4416
  process.exit(1);
4361
4417
  }
4362
4418
  success(`Switched to ${pc15.bold(targetBranch)}`);
4363
- info(`Your changes from ${pc15.bold(currentBranch ?? "previous branch")} are saved.`);
4364
- info(`Use ${pc15.bold("contrib save --restore")} to bring them back.`);
4419
+ info(`Your changes from ${pc15.bold(currentBranch ?? "previous branch")} are saved.`, "");
4420
+ info(`Use ${pc15.bold("contrib save --restore")} to bring them back.`, "");
4365
4421
  return;
4366
4422
  }
4367
4423
  const result = await checkoutBranch(targetBranch);
@@ -4428,8 +4484,8 @@ var sync_default = defineCommand13({
4428
4484
  }
4429
4485
  if (!await refExists(syncSource.ref)) {
4430
4486
  error(`Remote ref ${pc16.bold(syncSource.ref)} does not exist.`);
4431
- info("This can happen if the branch was renamed or deleted on the remote.");
4432
- info(`Check your config: the base branch may need updating via ${pc16.bold("contrib setup")}.`);
4487
+ info("This can happen if the branch was renamed or deleted on the remote.", "");
4488
+ info(`Check your config: the base branch may need updating via ${pc16.bold("contrib setup")}.`, "");
4433
4489
  process.exit(1);
4434
4490
  }
4435
4491
  let allowMergeCommit = false;
@@ -4506,10 +4562,10 @@ var sync_default = defineCommand13({
4506
4562
  const remoteRef = syncSource.ref;
4507
4563
  await updateLocalBranch(baseBranch, remoteRef);
4508
4564
  success(`Reset ${pc16.bold(baseBranch)} to ${pc16.bold(remoteRef)}.`);
4509
- success(`✅ ${pc16.bold(baseBranch)} is now in sync with ${syncSource.ref}`);
4565
+ success(`${pc16.bold(baseBranch)} is now in sync with ${syncSource.ref}`);
4510
4566
  console.log();
4511
- info(`Your commits are safe on ${pc16.bold(newBranchName)}.`);
4512
- info(`Run ${pc16.bold(`git checkout ${newBranchName}`)} then ${pc16.bold("contrib update")} to rebase onto the synced ${pc16.bold(baseBranch)}.`);
4567
+ info(`Your commits are safe on ${pc16.bold(newBranchName)}.`, "");
4568
+ info(`Run ${pc16.bold(`git checkout ${newBranchName}`)} then ${pc16.bold("contrib update")} to rebase onto the synced ${pc16.bold(baseBranch)}.`, "");
4513
4569
  return;
4514
4570
  }
4515
4571
  allowMergeCommit = true;
@@ -4532,11 +4588,11 @@ var sync_default = defineCommand13({
4532
4588
  error(`Pull failed: ${pullResult.stderr.trim()}`);
4533
4589
  } else {
4534
4590
  error(`Fast-forward pull failed. Your local ${pc16.bold(baseBranch)} may have diverged.`);
4535
- info(`Use ${pc16.bold("contrib sync")} again and choose "Move my commits to a new feature branch" to fix this.`);
4591
+ info(`Use ${pc16.bold("contrib sync")} again and choose "Move my commits to a new feature branch" to fix this.`, "");
4536
4592
  }
4537
4593
  process.exit(1);
4538
4594
  }
4539
- success(`✅ ${baseBranch} is now in sync with ${syncSource.ref}`);
4595
+ success(`${baseBranch} is now in sync with ${syncSource.ref}`);
4540
4596
  if (hasDevBranch(workflow) && role === "maintainer") {
4541
4597
  const mainDiv = await getDivergence(config.mainBranch, `${origin}/${config.mainBranch}`);
4542
4598
  if (mainDiv.behind > 0) {
@@ -4545,7 +4601,7 @@ var sync_default = defineCommand13({
4545
4601
  if (mainCoResult.exitCode === 0) {
4546
4602
  const mainPullResult = await pullFastForwardOnly(origin, config.mainBranch);
4547
4603
  if (mainPullResult.exitCode === 0) {
4548
- success(`✅ ${config.mainBranch} is now in sync with ${origin}/${config.mainBranch}`);
4604
+ success(`${config.mainBranch} is now in sync with ${origin}/${config.mainBranch}`);
4549
4605
  }
4550
4606
  }
4551
4607
  await checkoutBranch(baseBranch);
@@ -4660,10 +4716,10 @@ var update_default = defineCommand14({
4660
4716
  }
4661
4717
  success(`Created ${pc17.bold(newBranchName)} with your changes.`);
4662
4718
  await updateLocalBranch(currentBranch, remoteRef);
4663
- info(`Reset ${pc17.bold(currentBranch)} back to ${pc17.bold(remoteRef)} — no damage done.`);
4719
+ info(`Reset ${pc17.bold(currentBranch)} back to ${pc17.bold(remoteRef)} — no damage done.`, "");
4664
4720
  console.log();
4665
4721
  success(`You're now on ${pc17.bold(newBranchName)} with all your work intact.`);
4666
- info(`Run ${pc17.bold("contrib update")} again to rebase onto latest ${pc17.bold(baseBranch)}.`);
4722
+ info(`Run ${pc17.bold("contrib update")} again to rebase onto latest ${pc17.bold(baseBranch)}.`, "");
4667
4723
  return;
4668
4724
  }
4669
4725
  if (await hasUncommittedChanges()) {
@@ -4674,7 +4730,7 @@ var update_default = defineCommand14({
4674
4730
  const mergedPR = await getMergedPRForBranch(currentBranch);
4675
4731
  if (mergedPR) {
4676
4732
  warn(`PR #${mergedPR.number} (${pc17.bold(mergedPR.title)}) has already been merged.`);
4677
- info(`Link: ${pc17.underline(mergedPR.url)}`);
4733
+ info(`Link: ${pc17.underline(mergedPR.url)}`, "");
4678
4734
  const localWork = await hasLocalWork(syncSource.remote, currentBranch);
4679
4735
  const hasWork = localWork.uncommitted || localWork.unpushedCommits > 0;
4680
4736
  if (hasWork) {
@@ -4741,11 +4797,11 @@ var update_default = defineCommand14({
4741
4797
  }
4742
4798
  if (rebaseResult2.exitCode !== 0) {
4743
4799
  warn("Rebase encountered conflicts. Resolve them manually, then run:");
4744
- info(` ${pc17.bold("git rebase --continue")}`);
4800
+ info(` ${pc17.bold("git rebase --continue")}`, "");
4745
4801
  } else {
4746
4802
  success(`Rebased ${pc17.bold(newBranchName)} onto ${pc17.bold(syncSource.ref)}.`);
4747
4803
  }
4748
- info(`All your changes are preserved. Run ${pc17.bold("contrib submit")} when ready to create a new PR.`);
4804
+ info(`All your changes are preserved. Run ${pc17.bold("contrib submit")} when ready to create a new PR.`, "");
4749
4805
  return;
4750
4806
  }
4751
4807
  warn("Discarding local changes...");
@@ -4762,7 +4818,7 @@ var update_default = defineCommand14({
4762
4818
  info(`Deleting stale branch ${pc17.bold(currentBranch)}...`);
4763
4819
  await forceDeleteBranch(currentBranch);
4764
4820
  success(`Deleted ${pc17.bold(currentBranch)}.`);
4765
- info(`Run ${pc17.bold("contrib start")} to begin a new feature branch.`);
4821
+ info(`Run ${pc17.bold("contrib start")} to begin a new feature branch.`, "");
4766
4822
  return;
4767
4823
  }
4768
4824
  info(`Updating ${pc17.bold(currentBranch)} with latest ${pc17.bold(baseBranch)}...`);
@@ -4823,7 +4879,7 @@ ${pc17.bold("\uD83D\uDCA1 AI Conflict Resolution Guidance:")}`);
4823
4879
  console.log(` Or abort: ${pc17.cyan("git rebase --abort")}`);
4824
4880
  process.exit(1);
4825
4881
  }
4826
- success(`✅ ${pc17.bold(currentBranch)} has been rebased onto latest ${pc17.bold(baseBranch)}`);
4882
+ success(`${pc17.bold(currentBranch)} has been rebased onto latest ${pc17.bold(baseBranch)}`);
4827
4883
  }
4828
4884
  });
4829
4885
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contribute-now",
3
- "version": "0.6.0",
3
+ "version": "0.6.1-dev.4075d32",
4
4
  "description": "Developer CLI that automates git workflows — branching, syncing, committing, and PRs — with multi-workflow and commit convention support.",
5
5
  "type": "module",
6
6
  "bin": {