contribute-now 0.6.1-staging.82b7b78 → 0.6.2-dev.313af88

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 +87 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10415,6 +10415,40 @@ ${conflictDiff.slice(0, 4000)}`;
10415
10415
  return null;
10416
10416
  }
10417
10417
  }
10418
+ function normalizeCommitGroups(changedFiles, groups) {
10419
+ const changedSet = new Set(changedFiles);
10420
+ const assignedFiles = new Set;
10421
+ const unknownFiles = new Set;
10422
+ const duplicateFiles = new Set;
10423
+ const normalizedGroups = groups.map((group) => {
10424
+ const uniqueFiles = new Set;
10425
+ const files = [];
10426
+ for (const file of group.files) {
10427
+ if (!changedSet.has(file)) {
10428
+ unknownFiles.add(file);
10429
+ continue;
10430
+ }
10431
+ if (uniqueFiles.has(file) || assignedFiles.has(file)) {
10432
+ duplicateFiles.add(file);
10433
+ continue;
10434
+ }
10435
+ uniqueFiles.add(file);
10436
+ assignedFiles.add(file);
10437
+ files.push(file);
10438
+ }
10439
+ return {
10440
+ ...group,
10441
+ files
10442
+ };
10443
+ }).filter((group) => group.files.length > 0);
10444
+ const unassignedFiles = changedFiles.filter((file) => !assignedFiles.has(file));
10445
+ return {
10446
+ groups: normalizedGroups,
10447
+ unknownFiles: [...unknownFiles],
10448
+ duplicateFiles: [...duplicateFiles],
10449
+ unassignedFiles
10450
+ };
10451
+ }
10418
10452
  async function generateCommitGroups(files, diffs, model, convention = "clean-commit") {
10419
10453
  const isLarge = files.length >= BATCH_CONFIG.LARGE_CHANGESET_THRESHOLD;
10420
10454
  const diffContent = isLarge ? createCompactDiff(files, diffs) : diffs.slice(0, 6000);
@@ -11200,6 +11234,15 @@ ${import_picocolors8.default.bold("Changed files:")}`);
11200
11234
  success(`Committed: ${import_picocolors8.default.bold(finalMessage)}`);
11201
11235
  }
11202
11236
  });
11237
+ function getFallbackGroupMessage(convention) {
11238
+ if (convention === "conventional") {
11239
+ return "chore: commit remaining changes";
11240
+ }
11241
+ if (convention === "clean-commit") {
11242
+ return "☕ chore: commit remaining changes";
11243
+ }
11244
+ return "commit remaining changes";
11245
+ }
11203
11246
  async function runGroupCommit(model, config) {
11204
11247
  const [copilotError, changedFiles] = await Promise.all([
11205
11248
  checkCopilotAvailable(),
@@ -11237,15 +11280,25 @@ ${import_picocolors8.default.bold("Changed files:")}`);
11237
11280
  error("AI could not produce commit groups. Try committing files manually.");
11238
11281
  process.exit(1);
11239
11282
  }
11240
- const changedSet = new Set(changedFiles);
11241
- for (const group of groups) {
11242
- const invalid = group.files.filter((f3) => !changedSet.has(f3));
11243
- if (invalid.length > 0) {
11244
- warn(`AI suggested unknown file(s): ${invalid.join(", ")} — removed from group.`);
11245
- }
11246
- group.files = group.files.filter((f3) => changedSet.has(f3));
11283
+ const normalized = normalizeCommitGroups(changedFiles, groups);
11284
+ if (normalized.unknownFiles.length > 0) {
11285
+ warn(`AI suggested unknown file(s): ${normalized.unknownFiles.join(", ")} removed from groups.`);
11286
+ }
11287
+ if (normalized.duplicateFiles.length > 0) {
11288
+ warn(`AI assigned duplicate file(s) across groups: ${normalized.duplicateFiles.join(", ")} — keeping the first assignment only.`);
11289
+ }
11290
+ let validGroups = normalized.groups;
11291
+ if (normalized.unassignedFiles.length > 0) {
11292
+ warn(`AI left ${normalized.unassignedFiles.length} file(s) ungrouped: ${normalized.unassignedFiles.join(", ")}. Creating a fallback group.`);
11293
+ const fallbackMessage = await regenerateGroupMessage(normalized.unassignedFiles, diffs, model, config.commitConvention) ?? getFallbackGroupMessage(config.commitConvention);
11294
+ validGroups = [
11295
+ ...validGroups,
11296
+ {
11297
+ files: normalized.unassignedFiles,
11298
+ message: fallbackMessage
11299
+ }
11300
+ ];
11247
11301
  }
11248
- let validGroups = groups.filter((g3) => g3.files.length > 0);
11249
11302
  if (validGroups.length === 0) {
11250
11303
  error("No valid groups remain after validation. Try committing files manually.");
11251
11304
  process.exit(1);
@@ -11291,7 +11344,17 @@ ${import_picocolors8.default.bold(`AI suggested ${validGroups.length} commit gro
11291
11344
  if (commitAll) {
11292
11345
  for (let i2 = 0;i2 < validGroups.length; i2++) {
11293
11346
  const group = validGroups[i2];
11294
- const stageResult = await stageFiles(group.files);
11347
+ const remainingChangedFiles = new Set(await getChangedFiles());
11348
+ const stageableFiles = group.files.filter((file) => remainingChangedFiles.has(file));
11349
+ const skippedFiles = group.files.filter((file) => !remainingChangedFiles.has(file));
11350
+ if (skippedFiles.length > 0) {
11351
+ warn(`Group ${i2 + 1} file(s) no longer have changes: ${skippedFiles.join(", ")}`);
11352
+ }
11353
+ if (stageableFiles.length === 0) {
11354
+ warn(`Skipped group ${i2 + 1}: no files remain to commit.`);
11355
+ continue;
11356
+ }
11357
+ const stageResult = await stageFiles(stageableFiles);
11295
11358
  if (stageResult.exitCode !== 0) {
11296
11359
  error(`Failed to stage group ${i2 + 1}: ${stageResult.stderr}`);
11297
11360
  continue;
@@ -11300,7 +11363,7 @@ ${import_picocolors8.default.bold(`AI suggested ${validGroups.length} commit gro
11300
11363
  if (commitResult.exitCode !== 0) {
11301
11364
  const detail = (commitResult.stderr || commitResult.stdout).trim();
11302
11365
  error(`Failed to commit group ${i2 + 1}: ${detail}`);
11303
- await unstageFiles(group.files);
11366
+ await unstageFiles(stageableFiles);
11304
11367
  continue;
11305
11368
  }
11306
11369
  committed++;
@@ -11360,7 +11423,18 @@ ${import_picocolors8.default.bold(`AI suggested ${validGroups.length} commit gro
11360
11423
  continue;
11361
11424
  }
11362
11425
  }
11363
- const stageResult = await stageFiles(group.files);
11426
+ const remainingChangedFiles = new Set(await getChangedFiles());
11427
+ const stageableFiles = group.files.filter((file) => remainingChangedFiles.has(file));
11428
+ const skippedFiles = group.files.filter((file) => !remainingChangedFiles.has(file));
11429
+ if (skippedFiles.length > 0) {
11430
+ warn(`Group ${i2 + 1} file(s) no longer have changes: ${skippedFiles.join(", ")}`);
11431
+ }
11432
+ if (stageableFiles.length === 0) {
11433
+ warn(`Skipped group ${i2 + 1}: no files remain to commit.`);
11434
+ actionDone = true;
11435
+ continue;
11436
+ }
11437
+ const stageResult = await stageFiles(stageableFiles);
11364
11438
  if (stageResult.exitCode !== 0) {
11365
11439
  error(`Failed to stage group ${i2 + 1}: ${stageResult.stderr}`);
11366
11440
  actionDone = true;
@@ -11370,7 +11444,7 @@ ${import_picocolors8.default.bold(`AI suggested ${validGroups.length} commit gro
11370
11444
  if (commitResult.exitCode !== 0) {
11371
11445
  const detail = (commitResult.stderr || commitResult.stdout).trim();
11372
11446
  error(`Failed to commit group ${i2 + 1}: ${detail}`);
11373
- await unstageFiles(group.files);
11447
+ await unstageFiles(stageableFiles);
11374
11448
  actionDone = true;
11375
11449
  continue;
11376
11450
  }
@@ -11395,7 +11469,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
11395
11469
  // package.json
11396
11470
  var package_default = {
11397
11471
  name: "contribute-now",
11398
- version: "0.6.1-staging.82b7b78",
11472
+ version: "0.6.2-dev.313af88",
11399
11473
  description: "Developer CLI that automates git workflows — branching, syncing, committing, and PRs — with multi-workflow and commit convention support.",
11400
11474
  type: "module",
11401
11475
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contribute-now",
3
- "version": "0.6.1-staging.82b7b78",
3
+ "version": "0.6.2-dev.313af88",
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": {