@bragduck/cli 2.27.2 → 2.28.0
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/bin/bragduck.js +115 -1
- package/dist/bin/bragduck.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/bragduck.js
CHANGED
|
@@ -3657,6 +3657,7 @@ var JiraService = class {
|
|
|
3657
3657
|
* Check if a user object matches the given identifier (accountId, email, or username)
|
|
3658
3658
|
*/
|
|
3659
3659
|
isMatchingUser(candidate, userIdentifier) {
|
|
3660
|
+
if (!candidate) return false;
|
|
3660
3661
|
return candidate.email === userIdentifier || candidate.emailAddress === userIdentifier || candidate.accountId === userIdentifier || candidate.username === userIdentifier || candidate.name === userIdentifier;
|
|
3661
3662
|
}
|
|
3662
3663
|
/**
|
|
@@ -3736,7 +3737,7 @@ var JiraService = class {
|
|
|
3736
3737
|
}
|
|
3737
3738
|
const isAssigned = issue.fields.assignee?.emailAddress === userEmail;
|
|
3738
3739
|
const isResolved = issue.fields.resolutiondate !== null && issue.fields.resolutiondate !== void 0;
|
|
3739
|
-
const userEdits = issue.changelog?.histories?.filter((history) => history.author
|
|
3740
|
+
const userEdits = issue.changelog?.histories?.filter((history) => history.author?.emailAddress === userEmail) || [];
|
|
3740
3741
|
const hasEdits = userEdits.length > 0;
|
|
3741
3742
|
if (isAssigned && isResolved) {
|
|
3742
3743
|
return {
|
|
@@ -3771,6 +3772,77 @@ var JiraService = class {
|
|
|
3771
3772
|
};
|
|
3772
3773
|
return Math.ceil(baseComplexity * multipliers[contributionType]);
|
|
3773
3774
|
}
|
|
3775
|
+
/**
|
|
3776
|
+
* Summarize the user's specific changes from changelog entries into human-readable lines.
|
|
3777
|
+
* This enriches the brag message so the AI refinement can generate a more specific brag.
|
|
3778
|
+
*/
|
|
3779
|
+
summarizeUserChanges(userChanges) {
|
|
3780
|
+
const MAX_LINES = 10;
|
|
3781
|
+
const allItems = [];
|
|
3782
|
+
for (const entry of userChanges) {
|
|
3783
|
+
for (const item of entry.items) {
|
|
3784
|
+
allItems.push(item);
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
if (allItems.length === 0) return "";
|
|
3788
|
+
const latestByField = /* @__PURE__ */ new Map();
|
|
3789
|
+
for (const item of allItems) {
|
|
3790
|
+
latestByField.set(item.field, { fromString: item.fromString, toString: item.toString });
|
|
3791
|
+
}
|
|
3792
|
+
const lines = [];
|
|
3793
|
+
for (const [field, change] of latestByField) {
|
|
3794
|
+
if (lines.length >= MAX_LINES) break;
|
|
3795
|
+
const from = change.fromString || "";
|
|
3796
|
+
const to = change.toString || "";
|
|
3797
|
+
switch (field.toLowerCase()) {
|
|
3798
|
+
case "status":
|
|
3799
|
+
lines.push(from ? `Moved status from '${from}' to '${to}'` : `Set status to '${to}'`);
|
|
3800
|
+
break;
|
|
3801
|
+
case "resolution":
|
|
3802
|
+
lines.push(to ? `Resolved as '${to}'` : "Reopened issue");
|
|
3803
|
+
break;
|
|
3804
|
+
case "assignee":
|
|
3805
|
+
lines.push(to ? `Assigned to ${to}` : "Unassigned");
|
|
3806
|
+
break;
|
|
3807
|
+
case "priority":
|
|
3808
|
+
lines.push(
|
|
3809
|
+
from ? `Changed priority from '${from}' to '${to}'` : `Set priority to '${to}'`
|
|
3810
|
+
);
|
|
3811
|
+
break;
|
|
3812
|
+
case "summary":
|
|
3813
|
+
lines.push("Updated issue title");
|
|
3814
|
+
break;
|
|
3815
|
+
case "description":
|
|
3816
|
+
lines.push("Updated description");
|
|
3817
|
+
break;
|
|
3818
|
+
case "comment":
|
|
3819
|
+
lines.push("Added comment");
|
|
3820
|
+
break;
|
|
3821
|
+
case "labels":
|
|
3822
|
+
lines.push(to ? `Updated labels: ${to}` : "Removed labels");
|
|
3823
|
+
break;
|
|
3824
|
+
case "fix version":
|
|
3825
|
+
case "fixversions":
|
|
3826
|
+
lines.push(to ? `Set fix version: ${to}` : "Removed fix version");
|
|
3827
|
+
break;
|
|
3828
|
+
case "sprint":
|
|
3829
|
+
lines.push(to ? `Moved to sprint: ${to}` : "Removed from sprint");
|
|
3830
|
+
break;
|
|
3831
|
+
case "story points":
|
|
3832
|
+
case "story point estimate":
|
|
3833
|
+
lines.push(`Set story points to ${to}`);
|
|
3834
|
+
break;
|
|
3835
|
+
default:
|
|
3836
|
+
if (to) {
|
|
3837
|
+
lines.push(`Updated ${field}`);
|
|
3838
|
+
}
|
|
3839
|
+
break;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
if (lines.length === 0) return "";
|
|
3843
|
+
return `User changes:
|
|
3844
|
+
${lines.map((l) => `- ${l}`).join("\n")}`;
|
|
3845
|
+
}
|
|
3774
3846
|
/**
|
|
3775
3847
|
* Fetch issues with optional filtering
|
|
3776
3848
|
*/
|
|
@@ -3933,6 +4005,14 @@ ${contribution.details}`;
|
|
|
3933
4005
|
${truncatedDesc}`;
|
|
3934
4006
|
}
|
|
3935
4007
|
}
|
|
4008
|
+
if (userChanges && userChanges.length > 0) {
|
|
4009
|
+
const changeSummary = this.summarizeUserChanges(userChanges);
|
|
4010
|
+
if (changeSummary) {
|
|
4011
|
+
message += `
|
|
4012
|
+
|
|
4013
|
+
${changeSummary}`;
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
3936
4016
|
let date;
|
|
3937
4017
|
if (contribution?.type === "created" || contribution?.type === "reported") {
|
|
3938
4018
|
date = issue.fields.created;
|
|
@@ -4133,6 +4213,7 @@ var ConfluenceService = class {
|
|
|
4133
4213
|
* Check if a user object matches the given identifier (accountId, email, or username)
|
|
4134
4214
|
*/
|
|
4135
4215
|
isMatchingUser(candidate, userIdentifier) {
|
|
4216
|
+
if (!candidate) return false;
|
|
4136
4217
|
return candidate.email === userIdentifier || candidate.emailAddress === userIdentifier || candidate.accountId === userIdentifier || candidate.username === userIdentifier || candidate.name === userIdentifier;
|
|
4137
4218
|
}
|
|
4138
4219
|
/**
|
|
@@ -4269,6 +4350,31 @@ var ConfluenceService = class {
|
|
|
4269
4350
|
};
|
|
4270
4351
|
return Math.ceil(baseSize * multipliers[contributionType]);
|
|
4271
4352
|
}
|
|
4353
|
+
/**
|
|
4354
|
+
* Summarize the user's version edits into human-readable lines.
|
|
4355
|
+
* This enriches the brag message so the AI refinement can generate a more specific brag.
|
|
4356
|
+
*/
|
|
4357
|
+
summarizeUserVersions(userVersions) {
|
|
4358
|
+
const MAX_ENTRIES = 5;
|
|
4359
|
+
const versionsWithMessages = userVersions.filter((v) => v.message && v.message.trim());
|
|
4360
|
+
if (versionsWithMessages.length > 0) {
|
|
4361
|
+
const lines = versionsWithMessages.slice(0, MAX_ENTRIES).map((v) => {
|
|
4362
|
+
const suffix = v.minorEdit ? " (minor edit)" : "";
|
|
4363
|
+
return `- v${v.number}: ${v.message.trim()}${suffix}`;
|
|
4364
|
+
});
|
|
4365
|
+
return `Edit notes:
|
|
4366
|
+
${lines.join("\n")}`;
|
|
4367
|
+
}
|
|
4368
|
+
if (userVersions.length > 0) {
|
|
4369
|
+
const major = userVersions.filter((v) => !v.minorEdit).length;
|
|
4370
|
+
const minor = userVersions.filter((v) => v.minorEdit).length;
|
|
4371
|
+
const parts = [];
|
|
4372
|
+
if (major > 0) parts.push(`${major} major`);
|
|
4373
|
+
if (minor > 0) parts.push(`${minor} minor`);
|
|
4374
|
+
return `Made ${userVersions.length} edit${userVersions.length > 1 ? "s" : ""} to this page (${parts.join(", ")})`;
|
|
4375
|
+
}
|
|
4376
|
+
return "";
|
|
4377
|
+
}
|
|
4272
4378
|
/**
|
|
4273
4379
|
* Fetch pages with optional filtering
|
|
4274
4380
|
*/
|
|
@@ -4425,6 +4531,14 @@ ${contribution.details}
|
|
|
4425
4531
|
|
|
4426
4532
|
[Confluence Page v${page.version?.number || 1}]`;
|
|
4427
4533
|
}
|
|
4534
|
+
if (userVersions && userVersions.length > 0) {
|
|
4535
|
+
const versionSummary = this.summarizeUserVersions(userVersions);
|
|
4536
|
+
if (versionSummary) {
|
|
4537
|
+
message += `
|
|
4538
|
+
|
|
4539
|
+
${versionSummary}`;
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4428
4542
|
let baseUrl = "https://confluence.atlassian.net";
|
|
4429
4543
|
if (instanceUrl) {
|
|
4430
4544
|
baseUrl = instanceUrl.startsWith("http") ? instanceUrl : `https://${instanceUrl}`;
|