@yemi33/minions 0.1.1000 → 0.1.1002
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/CHANGELOG.md +3 -3
- package/engine/ado.js +24 -0
- package/engine/lifecycle.js +40 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.1002 (2026-04-15)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- fix stopAfter=0 watch expiry — run forever for all conditions (#1117)
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
- gate auto-fix conflict dispatch behind autoFixConflicts flag
|
|
26
26
|
|
|
27
27
|
### Fixes
|
|
28
|
+
- extend auto-link fallback to ADO projects
|
|
29
|
+
- auto-link existing GitHub PR when agent completes without creating one
|
|
28
30
|
- preserve ordered lists across blank lines in markdown renderer
|
|
29
31
|
- restore CC rendering and tab bar
|
|
30
32
|
- restore WATCH_ABSOLUTE_CONDITIONS import in watches.js lost in #1117 squash merge
|
|
@@ -43,8 +45,6 @@
|
|
|
43
45
|
- address review feedback — move writeToInbox outside lock, add absolute condition auto-expire
|
|
44
46
|
- fix watches feature gaps — human notifications, branch stub, status-change init, unique keys
|
|
45
47
|
- skip isAlreadyDispatched in needsReReview to allow re-review within 1hr
|
|
46
|
-
- skip SessionStart hook settings test on CI
|
|
47
|
-
- loop queue flush so messages queued during combined send aren't orphaned
|
|
48
48
|
|
|
49
49
|
### Other
|
|
50
50
|
- docs: update CLAUDE.md with recent Minions architecture changes
|
package/engine/ado.js
CHANGED
|
@@ -890,6 +890,29 @@ const isAdoThrottled = () => _adoThrottle.isThrottled();
|
|
|
890
890
|
/** Returns a snapshot of the current throttle state. Calls isAdoThrottled() for a fresh value. */
|
|
891
891
|
const getAdoThrottleState = () => _adoThrottle.getState();
|
|
892
892
|
|
|
893
|
+
/**
|
|
894
|
+
* Query ADO for an open PR on a specific branch.
|
|
895
|
+
* Used as a last-resort fallback when an agent completes without logging a PR URL
|
|
896
|
+
* but a PR may already exist from a prior orphaned dispatch.
|
|
897
|
+
* @param {object} project — project config with adoOrg, adoProject, repositoryId, prUrlBase
|
|
898
|
+
* @param {string} branch — source branch name (without refs/heads/ prefix)
|
|
899
|
+
* @returns {{ prNumber: number, url: string }|null}
|
|
900
|
+
*/
|
|
901
|
+
async function findOpenPrOnBranch(project, branch) {
|
|
902
|
+
if (!project.adoOrg || !project.adoProject || !project.repositoryId || !branch) return null;
|
|
903
|
+
const token = await getAdoToken();
|
|
904
|
+
if (!token) return null;
|
|
905
|
+
const orgBase = shared.getAdoOrgBase(project);
|
|
906
|
+
const sourceRef = encodeURIComponent(`refs/heads/${branch}`);
|
|
907
|
+
const url = `${orgBase}/${project.adoProject}/_apis/git/repositories/${project.repositoryId}/pullrequests?searchCriteria.status=active&searchCriteria.sourceRefName=${sourceRef}&api-version=7.1`;
|
|
908
|
+
const data = await adoFetch(url, token);
|
|
909
|
+
const pr = (data.value || [])[0];
|
|
910
|
+
if (!pr) return null;
|
|
911
|
+
const prNumber = pr.pullRequestId;
|
|
912
|
+
const prUrl = project.prUrlBase ? `${project.prUrlBase}${prNumber}` : `https://dev.azure.com/${project.adoOrg}/${project.adoProject}/_git/${project.repositoryId}/pullrequest/${prNumber}`;
|
|
913
|
+
return { prNumber, url: prUrl };
|
|
914
|
+
}
|
|
915
|
+
|
|
893
916
|
/** Reset throttle state — exported for testing only. */
|
|
894
917
|
function _resetAdoThrottle() {
|
|
895
918
|
_adoThrottle._reset();
|
|
@@ -913,6 +936,7 @@ module.exports = {
|
|
|
913
936
|
getAdoThrottleState,
|
|
914
937
|
fetchAdoPrMetadata,
|
|
915
938
|
fetchSinglePrBuildStatus,
|
|
939
|
+
findOpenPrOnBranch,
|
|
916
940
|
_resetAdoThrottle, // exported for testing
|
|
917
941
|
_setAdoThrottleForTest, // exported for testing
|
|
918
942
|
};
|
package/engine/lifecycle.js
CHANGED
|
@@ -1792,6 +1792,46 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
|
|
|
1792
1792
|
}
|
|
1793
1793
|
}
|
|
1794
1794
|
}
|
|
1795
|
+
// Last resort: query the platform directly for an open PR on this branch.
|
|
1796
|
+
// Handles the case where a prior orphaned dispatch created a PR but the engine
|
|
1797
|
+
// never processed its output — so the PR exists on the platform but not in pull-requests.json.
|
|
1798
|
+
if (!existingPrFound && meta?.branch) {
|
|
1799
|
+
const projectObj = shared.getProjects(config).find(p => p.name === meta?.project?.name);
|
|
1800
|
+
if (projectObj) {
|
|
1801
|
+
try {
|
|
1802
|
+
let found = null;
|
|
1803
|
+
if (projectObj.repoHost === 'github') {
|
|
1804
|
+
const ghSlug = projectObj.prUrlBase?.match(/github\.com\/([^/]+\/[^/]+)\/pull/)?.[1];
|
|
1805
|
+
if (ghSlug) {
|
|
1806
|
+
const raw = await execAsync(`gh pr list --head "${meta.branch}" --repo ${ghSlug} --json number,url,state --limit 1`, { timeout: 15000, windowsHide: true });
|
|
1807
|
+
const hits = JSON.parse(raw || '[]');
|
|
1808
|
+
if (hits.length > 0 && hits[0].state === 'OPEN') found = { prNumber: hits[0].number, url: hits[0].url };
|
|
1809
|
+
}
|
|
1810
|
+
} else {
|
|
1811
|
+
found = await require('./ado').findOpenPrOnBranch(projectObj, meta.branch);
|
|
1812
|
+
}
|
|
1813
|
+
if (found) {
|
|
1814
|
+
const fullId = `PR-${found.prNumber}`;
|
|
1815
|
+
const prPath = shared.projectPrPath(projectObj);
|
|
1816
|
+
mutateJsonFileLocked(prPath, prs => {
|
|
1817
|
+
if (!Array.isArray(prs)) prs = [];
|
|
1818
|
+
if (prs.some(p => p.id === fullId)) return prs;
|
|
1819
|
+
prs.push({
|
|
1820
|
+
id: fullId, prNumber: found.prNumber, title: meta.item?.title || '',
|
|
1821
|
+
agent: agentId, branch: meta.branch, reviewStatus: 'pending',
|
|
1822
|
+
status: PR_STATUS.ACTIVE, created: ts(), url: found.url,
|
|
1823
|
+
prdItems: meta.item?.id ? [meta.item.id] : [],
|
|
1824
|
+
sourcePlan: meta.item?.sourcePlan || '', itemType: meta.item?.itemType || '',
|
|
1825
|
+
});
|
|
1826
|
+
return prs;
|
|
1827
|
+
});
|
|
1828
|
+
if (meta.item?.id) addPrLink(fullId, meta.item.id);
|
|
1829
|
+
log('info', `Auto-linked existing PR ${fullId} on branch ${meta.branch} for ${meta.item?.id}`);
|
|
1830
|
+
existingPrFound = true;
|
|
1831
|
+
}
|
|
1832
|
+
} catch (e) { log('warn', `PR lookup for branch ${meta.branch}: ${e.message}`); }
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1795
1835
|
if (!existingPrFound) {
|
|
1796
1836
|
const noPrWiPath = resolveWorkItemPath(meta);
|
|
1797
1837
|
if (noPrWiPath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1002",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|