@yemi33/minions 0.1.1994 → 0.1.1995
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/engine/ado.js +22 -1
- package/engine/github.js +22 -1
- package/engine/lifecycle.js +8 -2
- package/engine/queries.js +16 -6
- package/package.json +1 -1
package/engine/ado.js
CHANGED
|
@@ -378,6 +378,15 @@ function applyAdoPrMetadata(pr, prData) {
|
|
|
378
378
|
updated = true;
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
+
// W-mpej044m00076d63: backfill `pr.created` from ADO's real creation
|
|
382
|
+
// timestamp. lifecycle.js attach paths omit `created` so this poll is the
|
|
383
|
+
// single source of truth for fresh records, and historical records missing
|
|
384
|
+
// `created` get backfilled the next time they're polled. Idempotent.
|
|
385
|
+
if (!pr.created && prData.creationDate) {
|
|
386
|
+
pr.created = prData.creationDate;
|
|
387
|
+
updated = true;
|
|
388
|
+
}
|
|
389
|
+
|
|
381
390
|
return updated;
|
|
382
391
|
}
|
|
383
392
|
|
|
@@ -720,6 +729,18 @@ async function pollPrStatus(config) {
|
|
|
720
729
|
pr.status = newStatus;
|
|
721
730
|
updated = true;
|
|
722
731
|
|
|
732
|
+
// W-mpej044m00076d63: persist platform close/merge timestamps on the
|
|
733
|
+
// normal-poll status flip. ADO does not split mergedAt vs closedAt at
|
|
734
|
+
// the API level — `closedDate` is set whenever a PR moves out of
|
|
735
|
+
// `active` (whether via merge or abandon). Mirror that into our own
|
|
736
|
+
// fields with the standard idempotency guard.
|
|
737
|
+
if (newStatus === PR_STATUS.MERGED && !pr.mergedAt) {
|
|
738
|
+
pr.mergedAt = prData.closedDate || ts();
|
|
739
|
+
}
|
|
740
|
+
if ((newStatus === PR_STATUS.ABANDONED || newStatus === PR_STATUS.CLOSED) && !pr.closedAt) {
|
|
741
|
+
pr.closedAt = prData.closedDate || ts();
|
|
742
|
+
}
|
|
743
|
+
|
|
723
744
|
if (newStatus === PR_STATUS.MERGED || newStatus === PR_STATUS.ABANDONED) {
|
|
724
745
|
if (pr.reviewStatus === 'waiting') {
|
|
725
746
|
pr.reviewStatus = newStatus === PR_STATUS.MERGED ? 'approved' : 'pending';
|
|
@@ -1070,7 +1091,7 @@ async function pollPrHumanComments(config) {
|
|
|
1070
1091
|
const threadsData = await adoFetch(threadsUrl, token);
|
|
1071
1092
|
const threads = threadsData.value || [];
|
|
1072
1093
|
|
|
1073
|
-
const cutoffStr = pr.humanFeedback?.lastProcessedCommentDate || pr.created || '1970-01-01';
|
|
1094
|
+
const cutoffStr = pr.humanFeedback?.lastProcessedCommentDate || pr.created || pr._attachedAt || '1970-01-01';
|
|
1074
1095
|
const cutoffMs = new Date(cutoffStr).getTime() || 0;
|
|
1075
1096
|
|
|
1076
1097
|
// Collect ALL human comments on the PR for full context. `allCommentDates`
|
package/engine/github.js
CHANGED
|
@@ -661,6 +661,16 @@ async function pollPrStatus(config) {
|
|
|
661
661
|
else if (prData.state === 'closed') newStatus = PR_STATUS.ABANDONED;
|
|
662
662
|
else if (prData.state === 'open') newStatus = PR_STATUS.ACTIVE;
|
|
663
663
|
|
|
664
|
+
// W-mpej044m00076d63: backfill `pr.created` from the platform's real
|
|
665
|
+
// creation timestamp. lifecycle.js attach paths deliberately omit
|
|
666
|
+
// `created` so this poll is the single source of truth — and historical
|
|
667
|
+
// records that pre-date the fix get backfilled the next time they're
|
|
668
|
+
// polled. Idempotent: only writes when missing.
|
|
669
|
+
if (!pr.created && prData.created_at) {
|
|
670
|
+
pr.created = prData.created_at;
|
|
671
|
+
updated = true;
|
|
672
|
+
}
|
|
673
|
+
|
|
664
674
|
// Track head SHA changes to detect new pushes (used for review re-dispatch gating)
|
|
665
675
|
if (prData.head?.sha && pr.headSha !== prData.head.sha) {
|
|
666
676
|
pr.headSha = prData.head.sha;
|
|
@@ -745,6 +755,17 @@ async function pollPrStatus(config) {
|
|
|
745
755
|
pr.status = newStatus;
|
|
746
756
|
updated = true;
|
|
747
757
|
|
|
758
|
+
// W-mpej044m00076d63: persist platform close/merge timestamps on the
|
|
759
|
+
// normal-poll status flip (previously only the abandoned-reconciliation
|
|
760
|
+
// path at ~line 1489 set mergedAt). Idempotency guard prevents a later
|
|
761
|
+
// reconciliation pass from overwriting an earlier-known value.
|
|
762
|
+
if (newStatus === PR_STATUS.MERGED && !pr.mergedAt) {
|
|
763
|
+
pr.mergedAt = prData.merged_at || prData.closed_at || ts();
|
|
764
|
+
}
|
|
765
|
+
if ((newStatus === PR_STATUS.ABANDONED || newStatus === PR_STATUS.CLOSED) && !pr.closedAt) {
|
|
766
|
+
pr.closedAt = prData.closed_at || ts();
|
|
767
|
+
}
|
|
768
|
+
|
|
748
769
|
if (newStatus === PR_STATUS.MERGED || newStatus === PR_STATUS.ABANDONED) {
|
|
749
770
|
// Resolve stale 'waiting' review status — won't be polled again after this
|
|
750
771
|
if (pr.reviewStatus === 'waiting') {
|
|
@@ -961,7 +982,7 @@ async function pollPrHumanComments(config) {
|
|
|
961
982
|
// fixture already populated the field.
|
|
962
983
|
_backfillViewerDidAuthor(allComments, viewerLogin);
|
|
963
984
|
|
|
964
|
-
const cutoffStr = pr.humanFeedback?.lastProcessedCommentDate || pr.created || '1970-01-01';
|
|
985
|
+
const cutoffStr = pr.humanFeedback?.lastProcessedCommentDate || pr.created || pr._attachedAt || '1970-01-01';
|
|
965
986
|
const cutoffMs = new Date(cutoffStr).getTime() || 0;
|
|
966
987
|
|
|
967
988
|
// Collect comments that should advance the cutoff separately from comments
|
package/engine/lifecycle.js
CHANGED
|
@@ -907,7 +907,11 @@ function syncPrsFromOutput(output, agentId, meta, config, opts = {}) {
|
|
|
907
907
|
branch: meta?.branch || '',
|
|
908
908
|
reviewStatus: 'pending',
|
|
909
909
|
status: PR_STATUS.ACTIVE,
|
|
910
|
-
|
|
910
|
+
// W-mpej044m00076d63: do NOT seed `created` with ts() (engine discovery time).
|
|
911
|
+
// The next GitHub/ADO poll backfills `pr.created` from the platform's real
|
|
912
|
+
// creation timestamp; `_attachedAt` is preserved as a fallback for downstream
|
|
913
|
+
// cutoffs (e.g. comment-poll cutoffStr) that need any timestamp at all.
|
|
914
|
+
_attachedAt: ts(),
|
|
911
915
|
url: prUrl,
|
|
912
916
|
prdItems: meta?.item?.id ? [meta.item.id] : [],
|
|
913
917
|
sourcePlan: meta?.item?.sourcePlan || '',
|
|
@@ -1221,7 +1225,9 @@ function _attachFoundPrToWi(found, meta, agentId, resultSummary, config) {
|
|
|
1221
1225
|
branch: meta.branch || '',
|
|
1222
1226
|
reviewStatus: 'pending',
|
|
1223
1227
|
status: PR_STATUS.ACTIVE,
|
|
1224
|
-
|
|
1228
|
+
// W-mpej044m00076d63: omit `created` — the next poll backfills from the
|
|
1229
|
+
// platform's real createdAt. `_attachedAt` is the discovery-time fallback.
|
|
1230
|
+
_attachedAt: ts(),
|
|
1225
1231
|
url: found.url,
|
|
1226
1232
|
prdItems: [meta.item.id],
|
|
1227
1233
|
sourcePlan: meta.item?.sourcePlan || '',
|
package/engine/queries.js
CHANGED
|
@@ -673,12 +673,22 @@ function getPullRequests(config) {
|
|
|
673
673
|
}
|
|
674
674
|
}
|
|
675
675
|
allPrs.sort((a, b) => {
|
|
676
|
-
//
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
//
|
|
676
|
+
// W-mpej044m00076d63: sort by the full ISO `created` timestamp DESC so
|
|
677
|
+
// same-day PRs preserve creation order (previously the slice-to-date
|
|
678
|
+
// collapsed every PR opened on the same day into one bucket, then tied
|
|
679
|
+
// on a noisy PR-number-derived integer that ignored owner/repo digits).
|
|
680
|
+
// The PR-number tiebreaker survives only as a guard for records that
|
|
681
|
+
// legitimately lack `created` (e.g. mid-poll backfill window).
|
|
682
|
+
const aCreated = a.created || '';
|
|
683
|
+
const bCreated = b.created || '';
|
|
684
|
+
if (aCreated && bCreated) {
|
|
685
|
+
const cmp = bCreated.localeCompare(aCreated);
|
|
686
|
+
if (cmp !== 0) return cmp;
|
|
687
|
+
} else if (aCreated || bCreated) {
|
|
688
|
+
// One missing — surface the one with a timestamp first (newer signal).
|
|
689
|
+
return bCreated ? 1 : -1;
|
|
690
|
+
}
|
|
691
|
+
// Final guard for missing-data records: keep PR-number desc (newer first).
|
|
682
692
|
const aNum = parseInt((a.id || '').replace(/\D/g, '')) || 0;
|
|
683
693
|
const bNum = parseInt((b.id || '').replace(/\D/g, '')) || 0;
|
|
684
694
|
return bNum - aNum;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1995",
|
|
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"
|