@gethmy/agent 1.19.0 → 1.20.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/cli.js +113 -32
- package/dist/index.js +113 -32
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -731,9 +731,29 @@ var init_config_validation = __esm(() => {
|
|
|
731
731
|
};
|
|
732
732
|
});
|
|
733
733
|
// ../harmony-shared/dist/branchRef.js
|
|
734
|
-
|
|
734
|
+
function extractBranchRef(description) {
|
|
735
|
+
if (!description)
|
|
736
|
+
return null;
|
|
737
|
+
for (const match of description.matchAll(BRANCH_REF_PATTERN)) {
|
|
738
|
+
const branch = match[1];
|
|
739
|
+
if (SAFE_GIT_REF_PATTERN.test(branch))
|
|
740
|
+
return branch;
|
|
741
|
+
}
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
function hasUnsafeDaemonBranchLine(description) {
|
|
745
|
+
if (!description)
|
|
746
|
+
return false;
|
|
747
|
+
for (const match of description.matchAll(DAEMON_BRANCH_LINE_PATTERN)) {
|
|
748
|
+
if (!SAFE_GIT_REF_PATTERN.test(match[1]))
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
var BRANCH_REF_PATTERN, DAEMON_BRANCH_LINE_PATTERN, SAFE_GIT_REF_PATTERN;
|
|
735
754
|
var init_branchRef = __esm(() => {
|
|
736
|
-
BRANCH_REF_PATTERN = /Branch:\s*`([^`]+)
|
|
755
|
+
BRANCH_REF_PATTERN = /Branch:\s*`([^`]+)`/g;
|
|
756
|
+
DAEMON_BRANCH_LINE_PATTERN = /^[ \t]*Branch:\s*`([^`]+)`/gm;
|
|
737
757
|
SAFE_GIT_REF_PATTERN = /^[a-zA-Z0-9/_.+-]+$/;
|
|
738
758
|
});
|
|
739
759
|
|
|
@@ -1540,6 +1560,7 @@ __export(exports_git_pr, {
|
|
|
1540
1560
|
findExistingPr: () => findExistingPr,
|
|
1541
1561
|
extractReviewedSha: () => extractReviewedSha,
|
|
1542
1562
|
extractPrUrl: () => extractPrUrl,
|
|
1563
|
+
extractAzurePrId: () => extractAzurePrId,
|
|
1543
1564
|
detectGitProvider: () => detectGitProvider,
|
|
1544
1565
|
deriveCiStatus: () => deriveCiStatus,
|
|
1545
1566
|
decidePrBranch: () => decidePrBranch,
|
|
@@ -1734,13 +1755,18 @@ async function checkPrMergeStatus(prUrl, cwd, provider) {
|
|
|
1734
1755
|
return "unknown";
|
|
1735
1756
|
}
|
|
1736
1757
|
}
|
|
1737
|
-
function
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
};
|
|
1758
|
+
function stripHeadsPrefix(ref) {
|
|
1759
|
+
return ref.replace(/^refs\/heads\//, "");
|
|
1760
|
+
}
|
|
1761
|
+
function branchOrSkip(branch) {
|
|
1762
|
+
if (!branch)
|
|
1763
|
+
return { kind: "skip", reason: "PR has no head branch name" };
|
|
1764
|
+
if (!SAFE_GIT_REF_PATTERN.test(branch)) {
|
|
1765
|
+
return { kind: "skip", reason: `unsafe git ref: ${branch}` };
|
|
1743
1766
|
}
|
|
1767
|
+
return { kind: "branch", branch };
|
|
1768
|
+
}
|
|
1769
|
+
function decideGithubPrBranch(rawJson) {
|
|
1744
1770
|
if (rawJson === null) {
|
|
1745
1771
|
return { kind: "skip", reason: "gh pr view failed" };
|
|
1746
1772
|
}
|
|
@@ -1759,25 +1785,74 @@ function decidePrBranch(provider, rawJson) {
|
|
|
1759
1785
|
reason: "fork PR (cross-repo head branch not on origin)"
|
|
1760
1786
|
};
|
|
1761
1787
|
}
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1788
|
+
return branchOrSkip(typeof parsed.headRefName === "string" ? parsed.headRefName : null);
|
|
1789
|
+
}
|
|
1790
|
+
function decideAzurePrBranch(rawJson) {
|
|
1791
|
+
if (rawJson === null) {
|
|
1792
|
+
return { kind: "skip", reason: "az repos pr show failed" };
|
|
1765
1793
|
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1794
|
+
let parsed;
|
|
1795
|
+
try {
|
|
1796
|
+
parsed = JSON.parse(rawJson.trim());
|
|
1797
|
+
} catch {
|
|
1798
|
+
return { kind: "skip", reason: "unparseable az repos pr show output" };
|
|
1799
|
+
}
|
|
1800
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
1801
|
+
return { kind: "skip", reason: "unparseable az repos pr show output" };
|
|
1802
|
+
}
|
|
1803
|
+
if (parsed.forkSource != null) {
|
|
1804
|
+
return {
|
|
1805
|
+
kind: "skip",
|
|
1806
|
+
reason: "fork PR (cross-repo head branch not on origin)"
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
const ref = typeof parsed.sourceRefName === "string" ? parsed.sourceRefName : null;
|
|
1810
|
+
return branchOrSkip(ref ? stripHeadsPrefix(ref) : null);
|
|
1811
|
+
}
|
|
1812
|
+
function decidePrBranch(provider, rawJson) {
|
|
1813
|
+
switch (provider) {
|
|
1814
|
+
case "github":
|
|
1815
|
+
return decideGithubPrBranch(rawJson);
|
|
1816
|
+
case "azure":
|
|
1817
|
+
return decideAzurePrBranch(rawJson);
|
|
1818
|
+
default:
|
|
1819
|
+
return {
|
|
1820
|
+
kind: "skip",
|
|
1821
|
+
reason: `PR-link review not yet supported for provider "${provider}"`
|
|
1822
|
+
};
|
|
1768
1823
|
}
|
|
1769
|
-
|
|
1824
|
+
}
|
|
1825
|
+
function extractAzurePrId(prUrl) {
|
|
1826
|
+
const m = prUrl.match(/pullrequest\/(\d+)/i);
|
|
1827
|
+
return m ? m[1] : null;
|
|
1770
1828
|
}
|
|
1771
1829
|
async function resolvePrHeadBranch(prUrl, cwd, provider) {
|
|
1772
|
-
if (provider
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1830
|
+
if (provider === "github") {
|
|
1831
|
+
try {
|
|
1832
|
+
const { stdout } = await execFileAsync("gh", ["pr", "view", prUrl, "--json", "headRefName,isCrossRepository"], { cwd, encoding: "utf-8", timeout: 1e4 });
|
|
1833
|
+
return decidePrBranch("github", stdout);
|
|
1834
|
+
} catch (err) {
|
|
1835
|
+
log.warn(TAG2, `gh pr view failed for ${prUrl}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1836
|
+
return decidePrBranch("github", null);
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
if (provider === "azure") {
|
|
1840
|
+
const prId = extractAzurePrId(prUrl);
|
|
1841
|
+
if (!prId) {
|
|
1842
|
+
return {
|
|
1843
|
+
kind: "skip",
|
|
1844
|
+
reason: `could not parse Azure PR id from ${prUrl}`
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
try {
|
|
1848
|
+
const { stdout } = await execFileAsync("az", ["repos", "pr", "show", "--id", prId, "--output", "json"], { cwd, encoding: "utf-8", timeout: 1e4 });
|
|
1849
|
+
return decidePrBranch("azure", stdout);
|
|
1850
|
+
} catch (err) {
|
|
1851
|
+
log.warn(TAG2, `az repos pr show failed for ${prUrl}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1852
|
+
return decidePrBranch("azure", null);
|
|
1853
|
+
}
|
|
1780
1854
|
}
|
|
1855
|
+
return decidePrBranch(provider, null);
|
|
1781
1856
|
}
|
|
1782
1857
|
function extractPrUrl(description) {
|
|
1783
1858
|
if (!description)
|
|
@@ -1909,7 +1984,11 @@ function buildPrBody(card, commitLog) {
|
|
|
1909
1984
|
].join(`
|
|
1910
1985
|
`);
|
|
1911
1986
|
}
|
|
1912
|
-
function createPullRequest(card, branchName, worktreePath, config, provider) {
|
|
1987
|
+
function createPullRequest(card, branchName, worktreePath, config, provider, existingPrUrl) {
|
|
1988
|
+
if (existingPrUrl) {
|
|
1989
|
+
log.info(TAG2, `Reusing existing PR from card description: ${existingPrUrl}`);
|
|
1990
|
+
return existingPrUrl;
|
|
1991
|
+
}
|
|
1913
1992
|
let commitLog = "";
|
|
1914
1993
|
try {
|
|
1915
1994
|
commitLog = execFileSync("git", ["log", "--oneline", `origin/${config.worktree.baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
|
|
@@ -2545,12 +2624,9 @@ function checkoutExistingBranch(basePath, branchName) {
|
|
|
2545
2624
|
return worktreeDir;
|
|
2546
2625
|
}
|
|
2547
2626
|
function extractBranchFromDescription(description) {
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
if (branch && !SAFE_GIT_REF_PATTERN.test(branch)) {
|
|
2552
|
-
log.warn(TAG7, `Extracted branch name contains unsafe characters: ${branch}`);
|
|
2553
|
-
return null;
|
|
2627
|
+
const branch = extractBranchRef(description);
|
|
2628
|
+
if (!branch && hasUnsafeDaemonBranchLine(description)) {
|
|
2629
|
+
log.warn(TAG7, "Daemon Branch: line contains unsafe characters; ignoring it");
|
|
2554
2630
|
}
|
|
2555
2631
|
return branch;
|
|
2556
2632
|
}
|
|
@@ -2568,6 +2644,11 @@ async function resolveReviewBranch(description, cwd) {
|
|
|
2568
2644
|
const resolved = await resolvePrHeadBranch(prUrl, cwd, provider);
|
|
2569
2645
|
return resolved;
|
|
2570
2646
|
}
|
|
2647
|
+
function reviewedFromPrUrl(description) {
|
|
2648
|
+
if (extractBranchFromDescription(description))
|
|
2649
|
+
return null;
|
|
2650
|
+
return extractPrUrl(description ?? null);
|
|
2651
|
+
}
|
|
2571
2652
|
var TAG7 = "review-worktree";
|
|
2572
2653
|
var init_review_worktree = __esm(() => {
|
|
2573
2654
|
init_dist();
|
|
@@ -5459,7 +5540,7 @@ async function postReviewComment(client, card, commentType, body) {
|
|
|
5459
5540
|
log.error(TAG20, `Failed to post review comment to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
|
|
5460
5541
|
}
|
|
5461
5542
|
}
|
|
5462
|
-
async function runReviewCompletion(client, card, result, config, worktreePath, branchName, sessionStats, runLogPath, workspaceId, agentSessionId, stateStore) {
|
|
5543
|
+
async function runReviewCompletion(client, card, result, config, worktreePath, branchName, sessionStats, runLogPath, workspaceId, agentSessionId, stateStore, resolvedFromPrUrl) {
|
|
5463
5544
|
let freshDesc;
|
|
5464
5545
|
try {
|
|
5465
5546
|
const { card: fresh } = await client.getCard(card.id);
|
|
@@ -5522,7 +5603,7 @@ ${runLogTail}
|
|
|
5522
5603
|
}
|
|
5523
5604
|
if (config.review.createPR && approvedBranch) {
|
|
5524
5605
|
const provider = detectGitProvider(worktreePath);
|
|
5525
|
-
prUrl = createPullRequest(card, approvedBranch, worktreePath, config, provider);
|
|
5606
|
+
prUrl = createPullRequest(card, approvedBranch, worktreePath, config, provider, resolvedFromPrUrl ?? null);
|
|
5526
5607
|
}
|
|
5527
5608
|
}
|
|
5528
5609
|
await addLabelByName(client, card, config.review.approvedLabel, config.review.approvedLabelColor);
|
|
@@ -6602,7 +6683,7 @@ class ReviewWorker {
|
|
|
6602
6683
|
currentTask: `Processing ${result.verdict} verdict`,
|
|
6603
6684
|
progressPercent: 80
|
|
6604
6685
|
});
|
|
6605
|
-
await runReviewCompletion(this.client, card, result, this.config, cwd, this.branchName, sessionStats, this.lastRunLogPath, this.workspaceId, this.sessionId, this.stateStore);
|
|
6686
|
+
await runReviewCompletion(this.client, card, result, this.config, cwd, this.branchName, sessionStats, this.lastRunLogPath, this.workspaceId, this.sessionId, this.stateStore, reviewedFromPrUrl(card.description));
|
|
6606
6687
|
await this.collectReviewGate(card, result);
|
|
6607
6688
|
} catch (err) {
|
|
6608
6689
|
this.state = "error";
|
package/dist/index.js
CHANGED
|
@@ -730,9 +730,29 @@ var init_config_validation = __esm(() => {
|
|
|
730
730
|
};
|
|
731
731
|
});
|
|
732
732
|
// ../harmony-shared/dist/branchRef.js
|
|
733
|
-
|
|
733
|
+
function extractBranchRef(description) {
|
|
734
|
+
if (!description)
|
|
735
|
+
return null;
|
|
736
|
+
for (const match of description.matchAll(BRANCH_REF_PATTERN)) {
|
|
737
|
+
const branch = match[1];
|
|
738
|
+
if (SAFE_GIT_REF_PATTERN.test(branch))
|
|
739
|
+
return branch;
|
|
740
|
+
}
|
|
741
|
+
return null;
|
|
742
|
+
}
|
|
743
|
+
function hasUnsafeDaemonBranchLine(description) {
|
|
744
|
+
if (!description)
|
|
745
|
+
return false;
|
|
746
|
+
for (const match of description.matchAll(DAEMON_BRANCH_LINE_PATTERN)) {
|
|
747
|
+
if (!SAFE_GIT_REF_PATTERN.test(match[1]))
|
|
748
|
+
return true;
|
|
749
|
+
}
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
var BRANCH_REF_PATTERN, DAEMON_BRANCH_LINE_PATTERN, SAFE_GIT_REF_PATTERN;
|
|
734
753
|
var init_branchRef = __esm(() => {
|
|
735
|
-
BRANCH_REF_PATTERN = /Branch:\s*`([^`]+)
|
|
754
|
+
BRANCH_REF_PATTERN = /Branch:\s*`([^`]+)`/g;
|
|
755
|
+
DAEMON_BRANCH_LINE_PATTERN = /^[ \t]*Branch:\s*`([^`]+)`/gm;
|
|
736
756
|
SAFE_GIT_REF_PATTERN = /^[a-zA-Z0-9/_.+-]+$/;
|
|
737
757
|
});
|
|
738
758
|
|
|
@@ -1539,6 +1559,7 @@ __export(exports_git_pr, {
|
|
|
1539
1559
|
findExistingPr: () => findExistingPr,
|
|
1540
1560
|
extractReviewedSha: () => extractReviewedSha,
|
|
1541
1561
|
extractPrUrl: () => extractPrUrl,
|
|
1562
|
+
extractAzurePrId: () => extractAzurePrId,
|
|
1542
1563
|
detectGitProvider: () => detectGitProvider,
|
|
1543
1564
|
deriveCiStatus: () => deriveCiStatus,
|
|
1544
1565
|
decidePrBranch: () => decidePrBranch,
|
|
@@ -1733,13 +1754,18 @@ async function checkPrMergeStatus(prUrl, cwd, provider) {
|
|
|
1733
1754
|
return "unknown";
|
|
1734
1755
|
}
|
|
1735
1756
|
}
|
|
1736
|
-
function
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
};
|
|
1757
|
+
function stripHeadsPrefix(ref) {
|
|
1758
|
+
return ref.replace(/^refs\/heads\//, "");
|
|
1759
|
+
}
|
|
1760
|
+
function branchOrSkip(branch) {
|
|
1761
|
+
if (!branch)
|
|
1762
|
+
return { kind: "skip", reason: "PR has no head branch name" };
|
|
1763
|
+
if (!SAFE_GIT_REF_PATTERN.test(branch)) {
|
|
1764
|
+
return { kind: "skip", reason: `unsafe git ref: ${branch}` };
|
|
1742
1765
|
}
|
|
1766
|
+
return { kind: "branch", branch };
|
|
1767
|
+
}
|
|
1768
|
+
function decideGithubPrBranch(rawJson) {
|
|
1743
1769
|
if (rawJson === null) {
|
|
1744
1770
|
return { kind: "skip", reason: "gh pr view failed" };
|
|
1745
1771
|
}
|
|
@@ -1758,25 +1784,74 @@ function decidePrBranch(provider, rawJson) {
|
|
|
1758
1784
|
reason: "fork PR (cross-repo head branch not on origin)"
|
|
1759
1785
|
};
|
|
1760
1786
|
}
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1787
|
+
return branchOrSkip(typeof parsed.headRefName === "string" ? parsed.headRefName : null);
|
|
1788
|
+
}
|
|
1789
|
+
function decideAzurePrBranch(rawJson) {
|
|
1790
|
+
if (rawJson === null) {
|
|
1791
|
+
return { kind: "skip", reason: "az repos pr show failed" };
|
|
1764
1792
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1793
|
+
let parsed;
|
|
1794
|
+
try {
|
|
1795
|
+
parsed = JSON.parse(rawJson.trim());
|
|
1796
|
+
} catch {
|
|
1797
|
+
return { kind: "skip", reason: "unparseable az repos pr show output" };
|
|
1798
|
+
}
|
|
1799
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
1800
|
+
return { kind: "skip", reason: "unparseable az repos pr show output" };
|
|
1801
|
+
}
|
|
1802
|
+
if (parsed.forkSource != null) {
|
|
1803
|
+
return {
|
|
1804
|
+
kind: "skip",
|
|
1805
|
+
reason: "fork PR (cross-repo head branch not on origin)"
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
const ref = typeof parsed.sourceRefName === "string" ? parsed.sourceRefName : null;
|
|
1809
|
+
return branchOrSkip(ref ? stripHeadsPrefix(ref) : null);
|
|
1810
|
+
}
|
|
1811
|
+
function decidePrBranch(provider, rawJson) {
|
|
1812
|
+
switch (provider) {
|
|
1813
|
+
case "github":
|
|
1814
|
+
return decideGithubPrBranch(rawJson);
|
|
1815
|
+
case "azure":
|
|
1816
|
+
return decideAzurePrBranch(rawJson);
|
|
1817
|
+
default:
|
|
1818
|
+
return {
|
|
1819
|
+
kind: "skip",
|
|
1820
|
+
reason: `PR-link review not yet supported for provider "${provider}"`
|
|
1821
|
+
};
|
|
1767
1822
|
}
|
|
1768
|
-
|
|
1823
|
+
}
|
|
1824
|
+
function extractAzurePrId(prUrl) {
|
|
1825
|
+
const m = prUrl.match(/pullrequest\/(\d+)/i);
|
|
1826
|
+
return m ? m[1] : null;
|
|
1769
1827
|
}
|
|
1770
1828
|
async function resolvePrHeadBranch(prUrl, cwd, provider) {
|
|
1771
|
-
if (provider
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1829
|
+
if (provider === "github") {
|
|
1830
|
+
try {
|
|
1831
|
+
const { stdout } = await execFileAsync("gh", ["pr", "view", prUrl, "--json", "headRefName,isCrossRepository"], { cwd, encoding: "utf-8", timeout: 1e4 });
|
|
1832
|
+
return decidePrBranch("github", stdout);
|
|
1833
|
+
} catch (err) {
|
|
1834
|
+
log.warn(TAG2, `gh pr view failed for ${prUrl}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1835
|
+
return decidePrBranch("github", null);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
if (provider === "azure") {
|
|
1839
|
+
const prId = extractAzurePrId(prUrl);
|
|
1840
|
+
if (!prId) {
|
|
1841
|
+
return {
|
|
1842
|
+
kind: "skip",
|
|
1843
|
+
reason: `could not parse Azure PR id from ${prUrl}`
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
try {
|
|
1847
|
+
const { stdout } = await execFileAsync("az", ["repos", "pr", "show", "--id", prId, "--output", "json"], { cwd, encoding: "utf-8", timeout: 1e4 });
|
|
1848
|
+
return decidePrBranch("azure", stdout);
|
|
1849
|
+
} catch (err) {
|
|
1850
|
+
log.warn(TAG2, `az repos pr show failed for ${prUrl}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1851
|
+
return decidePrBranch("azure", null);
|
|
1852
|
+
}
|
|
1779
1853
|
}
|
|
1854
|
+
return decidePrBranch(provider, null);
|
|
1780
1855
|
}
|
|
1781
1856
|
function extractPrUrl(description) {
|
|
1782
1857
|
if (!description)
|
|
@@ -1908,7 +1983,11 @@ function buildPrBody(card, commitLog) {
|
|
|
1908
1983
|
].join(`
|
|
1909
1984
|
`);
|
|
1910
1985
|
}
|
|
1911
|
-
function createPullRequest(card, branchName, worktreePath, config, provider) {
|
|
1986
|
+
function createPullRequest(card, branchName, worktreePath, config, provider, existingPrUrl) {
|
|
1987
|
+
if (existingPrUrl) {
|
|
1988
|
+
log.info(TAG2, `Reusing existing PR from card description: ${existingPrUrl}`);
|
|
1989
|
+
return existingPrUrl;
|
|
1990
|
+
}
|
|
1912
1991
|
let commitLog = "";
|
|
1913
1992
|
try {
|
|
1914
1993
|
commitLog = execFileSync("git", ["log", "--oneline", `origin/${config.worktree.baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
|
|
@@ -2544,12 +2623,9 @@ function checkoutExistingBranch(basePath, branchName) {
|
|
|
2544
2623
|
return worktreeDir;
|
|
2545
2624
|
}
|
|
2546
2625
|
function extractBranchFromDescription(description) {
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
if (branch && !SAFE_GIT_REF_PATTERN.test(branch)) {
|
|
2551
|
-
log.warn(TAG7, `Extracted branch name contains unsafe characters: ${branch}`);
|
|
2552
|
-
return null;
|
|
2626
|
+
const branch = extractBranchRef(description);
|
|
2627
|
+
if (!branch && hasUnsafeDaemonBranchLine(description)) {
|
|
2628
|
+
log.warn(TAG7, "Daemon Branch: line contains unsafe characters; ignoring it");
|
|
2553
2629
|
}
|
|
2554
2630
|
return branch;
|
|
2555
2631
|
}
|
|
@@ -2567,6 +2643,11 @@ async function resolveReviewBranch(description, cwd) {
|
|
|
2567
2643
|
const resolved = await resolvePrHeadBranch(prUrl, cwd, provider);
|
|
2568
2644
|
return resolved;
|
|
2569
2645
|
}
|
|
2646
|
+
function reviewedFromPrUrl(description) {
|
|
2647
|
+
if (extractBranchFromDescription(description))
|
|
2648
|
+
return null;
|
|
2649
|
+
return extractPrUrl(description ?? null);
|
|
2650
|
+
}
|
|
2570
2651
|
var TAG7 = "review-worktree";
|
|
2571
2652
|
var init_review_worktree = __esm(() => {
|
|
2572
2653
|
init_dist();
|
|
@@ -5458,7 +5539,7 @@ async function postReviewComment(client, card, commentType, body) {
|
|
|
5458
5539
|
log.error(TAG20, `Failed to post review comment to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
|
|
5459
5540
|
}
|
|
5460
5541
|
}
|
|
5461
|
-
async function runReviewCompletion(client, card, result, config, worktreePath, branchName, sessionStats, runLogPath, workspaceId, agentSessionId, stateStore) {
|
|
5542
|
+
async function runReviewCompletion(client, card, result, config, worktreePath, branchName, sessionStats, runLogPath, workspaceId, agentSessionId, stateStore, resolvedFromPrUrl) {
|
|
5462
5543
|
let freshDesc;
|
|
5463
5544
|
try {
|
|
5464
5545
|
const { card: fresh } = await client.getCard(card.id);
|
|
@@ -5521,7 +5602,7 @@ ${runLogTail}
|
|
|
5521
5602
|
}
|
|
5522
5603
|
if (config.review.createPR && approvedBranch) {
|
|
5523
5604
|
const provider = detectGitProvider(worktreePath);
|
|
5524
|
-
prUrl = createPullRequest(card, approvedBranch, worktreePath, config, provider);
|
|
5605
|
+
prUrl = createPullRequest(card, approvedBranch, worktreePath, config, provider, resolvedFromPrUrl ?? null);
|
|
5525
5606
|
}
|
|
5526
5607
|
}
|
|
5527
5608
|
await addLabelByName(client, card, config.review.approvedLabel, config.review.approvedLabelColor);
|
|
@@ -6601,7 +6682,7 @@ class ReviewWorker {
|
|
|
6601
6682
|
currentTask: `Processing ${result.verdict} verdict`,
|
|
6602
6683
|
progressPercent: 80
|
|
6603
6684
|
});
|
|
6604
|
-
await runReviewCompletion(this.client, card, result, this.config, cwd, this.branchName, sessionStats, this.lastRunLogPath, this.workspaceId, this.sessionId, this.stateStore);
|
|
6685
|
+
await runReviewCompletion(this.client, card, result, this.config, cwd, this.branchName, sessionStats, this.lastRunLogPath, this.workspaceId, this.sessionId, this.stateStore, reviewedFromPrUrl(card.description));
|
|
6605
6686
|
await this.collectReviewGate(card, result);
|
|
6606
6687
|
} catch (err) {
|
|
6607
6688
|
this.state = "error";
|