@ddtcorex/dsh-maestro-review 0.5.0 → 0.5.1

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 (48) hide show
  1. package/README.md +2 -1
  2. package/lib/ci-coexist.d.ts +6 -4
  3. package/lib/ci-coexist.d.ts.map +1 -1
  4. package/lib/ci-coexist.js +6 -4
  5. package/lib/ci-coexist.js.map +1 -1
  6. package/lib/events.d.ts +4 -0
  7. package/lib/events.d.ts.map +1 -1
  8. package/lib/gitlab-client.d.ts +7 -0
  9. package/lib/gitlab-client.d.ts.map +1 -1
  10. package/lib/gitlab-client.js +21 -0
  11. package/lib/gitlab-client.js.map +1 -1
  12. package/lib/incremental.d.ts.map +1 -1
  13. package/lib/incremental.js +3 -2
  14. package/lib/incremental.js.map +1 -1
  15. package/lib/orchestrator.d.ts +5 -2
  16. package/lib/orchestrator.d.ts.map +1 -1
  17. package/lib/orchestrator.js +44 -11
  18. package/lib/orchestrator.js.map +1 -1
  19. package/lib/providers/ci-trigger.d.ts +2 -1
  20. package/lib/providers/ci-trigger.d.ts.map +1 -1
  21. package/lib/providers/ci-trigger.js +12 -8
  22. package/lib/providers/ci-trigger.js.map +1 -1
  23. package/lib/providers/gitlab.d.ts.map +1 -1
  24. package/lib/providers/gitlab.js +16 -4
  25. package/lib/providers/gitlab.js.map +1 -1
  26. package/lib/review-history.d.ts +2 -1
  27. package/lib/review-history.d.ts.map +1 -1
  28. package/lib/review-history.js +67 -40
  29. package/lib/review-history.js.map +1 -1
  30. package/lib/review-intake.d.ts +9 -0
  31. package/lib/review-intake.d.ts.map +1 -1
  32. package/lib/review-intake.js +34 -1
  33. package/lib/review-intake.js.map +1 -1
  34. package/lib/review-signals.d.ts.map +1 -1
  35. package/lib/review-signals.js +9 -3
  36. package/lib/review-signals.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/host/ci-coexist.ts +6 -4
  39. package/src/host/events.ts +4 -0
  40. package/src/host/gitlab-client.ts +21 -0
  41. package/src/host/incremental.ts +3 -2
  42. package/src/host/orchestrator.ts +47 -11
  43. package/src/host/providers/ci-trigger.ts +14 -10
  44. package/src/host/providers/gitlab.ts +19 -5
  45. package/src/host/review-history.ts +65 -35
  46. package/src/host/review-intake.ts +36 -1
  47. package/src/host/review-signals.ts +6 -4
  48. package/templates/source-project.gitlab-ci.yml +1 -2
@@ -1 +1 @@
1
- {"version":3,"file":"review-history.js","sourceRoot":"","sources":["../src/host/review-history.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"review-history.js","sourceRoot":"","sources":["../src/host/review-history.ts"],"names":[],"mappings":"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"}
@@ -3,5 +3,14 @@ export interface RouteOptions {
3
3
  /** When true, an MR update carrying new commits routes a push re-review. */
4
4
  pushEnabled?: boolean;
5
5
  }
6
+ /** Actionable provider-layer drop reasons. Generic non-review GitLab noise
7
+ * (closes, label edits, ...) intentionally has no reason and stays silent. */
8
+ export type DropReason = 'invalid-identity' | 'push-gate-off';
9
+ /**
10
+ * Name why this webhook body will NOT route at the provider layer, or
11
+ * `undefined` when it routes (or is generic noise the provider ignores).
12
+ * Pure — the provider logs the returned reason with project/mr context.
13
+ */
14
+ export declare function describeDrop(body: unknown, botUsername: string, options?: RouteOptions): DropReason | undefined;
6
15
  export declare function routeGitlabReviewRequest(body: unknown, botUsername: string, options?: RouteOptions): ReviewRequest | undefined;
7
16
  //# sourceMappingURL=review-intake.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"review-intake.d.ts","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,aAAa,EAAe,MAAM,aAAa,CAAA;AA8C1F,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,aAAa,GAAG,SAAS,CAsClI"}
1
+ {"version":3,"file":"review-intake.d.ts","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,aAAa,EAAe,MAAM,aAAa,CAAA;AA2D1F,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;8EAC8E;AAC9E,MAAM,MAAM,UAAU,GAAG,kBAAkB,GAAG,eAAe,CAAA;AAE7D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,UAAU,GAAG,SAAS,CAWnH;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,aAAa,GAAG,SAAS,CAsClI"}
@@ -29,6 +29,19 @@ function isMentioned(text, botUsername) {
29
29
  const escaped = botUsername.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
30
30
  return new RegExp(`(^|[^A-Za-z0-9_.-])@${escaped}(?=$|[^A-Za-z0-9_.-])`, 'i').test(text);
31
31
  }
32
+ /**
33
+ * Short head-sha hint for the in-flight key: prefers `last_commit.id`, falls
34
+ * back to `checkout_sha`. Returns `undefined` when the body carries no sha.
35
+ */
36
+ function shortPushSha(attributes) {
37
+ const lastCommit = record(attributes.last_commit);
38
+ const raw = typeof lastCommit?.id === 'string' ? lastCommit.id
39
+ : typeof attributes.checkout_sha === 'string' ? attributes.checkout_sha
40
+ : undefined;
41
+ if (raw === undefined || raw.trim() === '')
42
+ return undefined;
43
+ return raw.slice(0, 8);
44
+ }
32
45
  function noteScope(attributes) {
33
46
  const position = record(attributes.position);
34
47
  if (position === undefined)
@@ -39,6 +52,26 @@ function noteScope(attributes) {
39
52
  return undefined;
40
53
  return { kind: 'discussion', discussionId: attributes.discussion_id, path, line };
41
54
  }
55
+ /**
56
+ * Name why this webhook body will NOT route at the provider layer, or
57
+ * `undefined` when it routes (or is generic noise the provider ignores).
58
+ * Pure — the provider logs the returned reason with project/mr context.
59
+ */
60
+ export function describeDrop(body, botUsername, options = {}) {
61
+ const value = record(body);
62
+ if (value === undefined || botUsername.trim() === '')
63
+ return 'invalid-identity';
64
+ const payload = mrPayload(value);
65
+ if (payload === undefined)
66
+ return 'invalid-identity';
67
+ if (value.object_kind === 'merge_request') {
68
+ const attributes = record(value.object_attributes);
69
+ const hasNewCommits = typeof attributes?.oldrev === 'string' && attributes.oldrev !== '';
70
+ if (hasNewCommits && options.pushEnabled !== true)
71
+ return 'push-gate-off';
72
+ }
73
+ return undefined;
74
+ }
42
75
  export function routeGitlabReviewRequest(body, botUsername, options = {}) {
43
76
  const value = record(body);
44
77
  if (value === undefined || botUsername.trim() === '')
@@ -56,7 +89,7 @@ export function routeGitlabReviewRequest(body, botUsername, options = {}) {
56
89
  if (options.pushEnabled === true) {
57
90
  const hasNewCommits = typeof attributes.oldrev === 'string' && attributes.oldrev !== '';
58
91
  if (hasNewCommits) {
59
- return { ...payload, trigger: 'push', mode: 'quick', scope: { kind: 'mr' } };
92
+ return { ...payload, trigger: 'push', mode: 'quick', scope: { kind: 'mr' }, pushSha: shortPushSha(attributes) };
60
93
  }
61
94
  }
62
95
  const reviewerChange = changes === undefined ? undefined : record(changes.reviewers);
@@ -1 +1 @@
1
- {"version":3,"file":"review-intake.js","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"review-intake.js","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"review-signals.d.ts","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvD;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAgBrJ"}
1
+ {"version":3,"file":"review-signals.d.ts","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,WAAW,aAAa;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvD;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAgBrJ"}
@@ -1,6 +1,12 @@
1
+ /**
2
+ * MR award-emoji acknowledgements: the MR shows "eyes" while a review runs and
3
+ * a final marker when it completes or fails. Signalling is best-effort — any
4
+ * GitLab error is swallowed so it can never fail the review itself.
5
+ */
1
6
  import { gitlabAuthHeaders } from './gitlab-auth.js';
7
+ import { fetchWithTimeout } from './gitlab-client.js';
2
8
  async function award(baseUrl, token, projectId, mrIid, name) {
3
- await fetch(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji`, {
9
+ await fetchWithTimeout(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji`, {
4
10
  method: 'POST',
5
11
  headers: { ...gitlabAuthHeaders(token), 'Content-Type': 'application/json' },
6
12
  body: JSON.stringify({ name }),
@@ -8,7 +14,7 @@ async function award(baseUrl, token, projectId, mrIid, name) {
8
14
  }
9
15
  /** Remove only this bot's stale running markers; other users' awards stay untouched. */
10
16
  async function unawardOwn(baseUrl, token, projectId, mrIid, botUsername) {
11
- const response = await fetch(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji`, {
17
+ const response = await fetchWithTimeout(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji`, {
12
18
  headers: gitlabAuthHeaders(token),
13
19
  });
14
20
  if (!response.ok)
@@ -17,7 +23,7 @@ async function unawardOwn(baseUrl, token, projectId, mrIid, botUsername) {
17
23
  for (const awardItem of Array.isArray(awards) ? awards : []) {
18
24
  if (awardItem.name !== 'eyes' || awardItem.user?.username !== botUsername || typeof awardItem.id !== 'number')
19
25
  continue;
20
- await fetch(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji/${awardItem.id}`, {
26
+ await fetchWithTimeout(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji/${awardItem.id}`, {
21
27
  method: 'DELETE',
22
28
  headers: gitlabAuthHeaders(token),
23
29
  }).catch(() => { });
@@ -1 +1 @@
1
- {"version":3,"file":"review-signals.js","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAYpD,KAAK,UAAU,KAAK,CAAC,OAAe,EAAE,KAAa,EAAE,SAAiB,EAAE,KAAa,EAAE,IAAY;IACjG,MAAM,KAAK,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,cAAc,EAAE;QACzF,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC5E,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;KAC/B,CAAC,CAAA;AACJ,CAAC;AAED,wFAAwF;AACxF,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,KAAa,EAAE,SAAiB,EAAE,KAAa,EAAE,WAAmB;IAC7G,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,cAAc,EAAE;QAC1G,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC;KAClC,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAM;IACxB,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwE,CAAA;IAC7G,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5D,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,QAAQ,KAAK,WAAW,IAAI,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ;YAAE,SAAQ;QACvH,MAAM,KAAK,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,gBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE;YACzG,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC;SAClC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAkG;IACpI,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;IACjE,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;gBAC/D,MAAM,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;YACvD,CAAC;YAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;QAC1D,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,OAAO;YAClB,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;gBAC/D,MAAM,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACzG,CAAC;YAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;QAC1D,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"review-signals.js","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAOrD,KAAK,UAAU,KAAK,CAAC,OAAe,EAAE,KAAa,EAAE,SAAiB,EAAE,KAAa,EAAE,IAAY;IACjG,MAAM,gBAAgB,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,cAAc,EAAE;QACpG,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC5E,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;KAC/B,CAAC,CAAA;AACJ,CAAC;AAED,wFAAwF;AACxF,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,KAAa,EAAE,SAAiB,EAAE,KAAa,EAAE,WAAmB;IAC7G,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,cAAc,EAAE;QACrH,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC;KAClC,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAM;IACxB,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwE,CAAA;IAC7G,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5D,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,QAAQ,KAAK,WAAW,IAAI,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ;YAAE,SAAQ;QACvH,MAAM,gBAAgB,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,gBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE;YACpH,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC;SAClC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAkG;IACpI,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;IACjE,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;gBAC/D,MAAM,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;YACvD,CAAC;YAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;QAC1D,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,OAAO;YAClB,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;gBAC/D,MAAM,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACzG,CAAC;YAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;QAC1D,CAAC;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ddtcorex/dsh-maestro-review",
3
3
  "private": false,
4
- "version": "0.5.0",
4
+ "version": "0.5.1",
5
5
  "description": "Maestro Review — pluggable ReviewProvider (GitLab/GitHub) + orchestrator for automated MR review",
6
6
  "type": "module",
7
7
  "main": "./lib/index.js",
@@ -2,10 +2,12 @@ import { gitlabAuthHeaders } from './gitlab-auth.js'
2
2
  import { parseReviewMarker } from './review-marker.js'
3
3
 
4
4
  /**
5
- * Coexistence checks (spec §4): the CI flow yields to any completed review of
6
- * the same head SHA (whatever flow posted it) and to an in-flight review
7
- * (eyes running-marker). Fetch failures fail open toward running — a missing
8
- * signal must never block a review, only a present one skips it.
5
+ * Coexistence checks (spec §4): the CI flow yields to a completed review of
6
+ * the same head SHA carrying a review marker (i.e. an earlier CI review —
7
+ * webhook reviews post marker-free and stay invisible here) and to an
8
+ * in-flight review (eyes running-marker). Fetch failures fail open toward
9
+ * running — a missing signal must never block a review, only a present one
10
+ * skips it.
9
11
  */
10
12
  export async function hasCompletedReviewForSha(
11
13
  fetcher: typeof fetch, baseUrl: string, token: string, projectId: number, mrIid: number, sha: string,
@@ -30,6 +30,10 @@ export interface ReviewRequest extends MrOpenedPayload {
30
30
  * webhook producer never sets it — webhook comments stay marker-free.
31
31
  */
32
32
  headSha?: string
33
+ /** Short (8-char) head-sha hint for `push` triggers, taken from the webhook
34
+ * body — feeds the in-flight key so two concurrent pushes stop deduping
35
+ * each other. Absent when the body carries no sha. */
36
+ pushSha?: string
33
37
  }
34
38
 
35
39
  export interface ReviewResult {
@@ -47,6 +47,27 @@ export function selectFileDiff(diffs: GitlabDiff[], path: string): string | unde
47
47
  return `--- ${d.old_path}\n+++ ${d.new_path}\n${d.diff}`
48
48
  }
49
49
 
50
+ /**
51
+ * `fetch` with a hard ceiling: aborts the request after `ms` (default 15s)
52
+ * and throws `GitLab API timeout after <ms>ms` on abort. The timer is always
53
+ * cleared on settle. Pre-agent lookups degrade the throw to `undefined` at
54
+ * their own call site; post-agent callers let it reach `writeFailedReport`.
55
+ */
56
+ export async function fetchWithTimeout(
57
+ url: string, init: RequestInit | undefined, ms = 15_000,
58
+ ): Promise<Response> {
59
+ const controller = new AbortController()
60
+ const timer = setTimeout(() => controller.abort(), ms)
61
+ try {
62
+ return await fetch(url, { ...init, signal: controller.signal })
63
+ } catch (err) {
64
+ if ((err as Error)?.name === 'AbortError') throw new Error(`GitLab API timeout after ${ms}ms`)
65
+ throw err
66
+ } finally {
67
+ clearTimeout(timer)
68
+ }
69
+ }
70
+
50
71
  interface GitlabDiffRefs {
51
72
  base_sha: string
52
73
  start_sha: string
@@ -1,4 +1,5 @@
1
1
  import { gitlabAuthHeaders } from './gitlab-auth.js'
2
+ import { fetchWithTimeout } from './gitlab-client.js'
2
3
  export interface CompareCommit {
3
4
  short_id?: string
4
5
  title?: string
@@ -56,7 +57,7 @@ export async function fetchMrDetailHeadSha(
56
57
  baseUrl: string, token: string, projectId: number, mrIid: number,
57
58
  ): Promise<string | undefined> {
58
59
  try {
59
- const response = await fetch(
60
+ const response = await fetchWithTimeout(
60
61
  `${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}`,
61
62
  { headers: gitlabAuthHeaders(token) },
62
63
  )
@@ -73,7 +74,7 @@ export async function fetchCompare(
73
74
  baseUrl: string, token: string, projectId: number, from: string, to: string,
74
75
  ): Promise<CompareResult | undefined> {
75
76
  try {
76
- const response = await fetch(
77
+ const response = await fetchWithTimeout(
77
78
  `${baseUrl}/api/v4/projects/${projectId}/repository/compare?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`,
78
79
  { headers: gitlabAuthHeaders(token) },
79
80
  )
@@ -524,7 +524,8 @@ const inFlightKeys = new Set<string>()
524
524
 
525
525
  function reviewKey(payload: ReviewRequest): string {
526
526
  const scope = payload.scope.kind === 'mr' ? 'mr' : `discussion:${payload.scope.discussionId}`
527
- return `${payload.projectId}:${payload.mrIid}:${payload.mode}:${scope}`
527
+ const sha = typeof payload.pushSha === 'string' && payload.pushSha !== '' ? `:${payload.pushSha}` : ''
528
+ return `${payload.projectId}:${payload.mrIid}:${payload.mode}:${scope}:${payload.trigger}${sha}`
528
529
  }
529
530
 
530
531
  /**
@@ -640,7 +641,10 @@ export async function runReviewAndAudit(payload: ReviewRequest, deps: ReviewAndA
640
641
  assertSafeId(payload.projectId, 'projectId')
641
642
  assertSafeId(payload.mrIid, 'mrIid')
642
643
  const key = reviewKey(payload)
643
- if (inFlightKeys.has(key)) return ''
644
+ if (inFlightKeys.has(key)) {
645
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`)
646
+ return ''
647
+ }
644
648
  inFlightKeys.add(key)
645
649
  try {
646
650
  const worktreePath = await deps.ensureWorktree(deps.localRepoPath, payload.sourceBranch, payload.projectId, payload.mrIid, reviewKeyHash(payload))
@@ -711,7 +715,10 @@ export async function runDiffOnlyReview(payload: ReviewRequest, deps: DiffOnlyRe
711
715
  assertSafeId(payload.projectId, 'projectId')
712
716
  assertSafeId(payload.mrIid, 'mrIid')
713
717
  const key = reviewKey(payload)
714
- if (inFlightKeys.has(key)) return ''
718
+ if (inFlightKeys.has(key)) {
719
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`)
720
+ return ''
721
+ }
715
722
  inFlightKeys.add(key)
716
723
  try {
717
724
  const { summary, failures } = await deps.runReviewer(payload)
@@ -741,12 +748,18 @@ export async function runDiffOnlyReview(payload: ReviewRequest, deps: DiffOnlyRe
741
748
  }
742
749
  }
743
750
 
744
- /** Decline a Deep request that lacks the local mapping it requires. */
745
- export async function declineUnmappedDeepReview(payload: ReviewRequest, deps: ReviewCommentDeps): Promise<void> {
751
+ /** Decline a Deep request that lacks the local mapping it requires.
752
+ * Resolves `true` when the decline was posted, `false` when a duplicate
753
+ * in-flight review is already handling this key (caller must not record a
754
+ * completion for work it did not do). */
755
+ export async function declineUnmappedDeepReview(payload: ReviewRequest, deps: ReviewCommentDeps): Promise<boolean> {
746
756
  assertSafeId(payload.projectId, 'projectId')
747
757
  assertSafeId(payload.mrIid, 'mrIid')
748
758
  const key = reviewKey(payload)
749
- if (inFlightKeys.has(key)) return
759
+ if (inFlightKeys.has(key)) {
760
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`)
761
+ return false
762
+ }
750
763
  inFlightKeys.add(key)
751
764
  const depsWithUrl = deps as unknown as { gitlabBaseUrl?: string; projectPath?: string }
752
765
  const baseUrl = depsWithUrl.gitlabBaseUrl
@@ -761,6 +774,7 @@ export async function declineUnmappedDeepReview(payload: ReviewRequest, deps: Re
761
774
  console.error(`maestro-orchestrator: posting review comment failed: ${err instanceof Error ? err.message : String(err)}`)
762
775
  await deps.writeFailedReport(payload.mrIid, body)
763
776
  }
777
+ return true
764
778
  } finally {
765
779
  inFlightKeys.delete(key)
766
780
  }
@@ -1203,25 +1217,29 @@ export function apply(ctx: Context, config: Config): void {
1203
1217
  // Unmapped reviewer assignments remain no-ops. Only an explicit mention
1204
1218
  // may opt into the intentionally limited, diff-only fallback below.
1205
1219
  if (mapping === undefined && payload.trigger !== 'mention') {
1220
+ console.error(`maestro-orchestrator: drop unmapped project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
1206
1221
  return { ok: true, failures: [], durationMs: Date.now() - t0 }
1207
1222
  }
1208
1223
  const triggers = resolveReviewTriggers(userConfig, mapping)
1209
- // Gated-off auto-triggers stay fully silent: no history, no signals, no comment.
1224
+ // Gated-off auto-triggers stay fully silent: no history, no signals, no comment (host log only).
1210
1225
  if (payload.trigger === 'reviewer-assignment' && !triggers.onAssign) {
1226
+ console.error(`maestro-orchestrator: drop assign-gate-off project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
1211
1227
  return { ok: true, failures: [], durationMs: Date.now() - t0 }
1212
1228
  }
1213
1229
  if (payload.trigger === 'push' && !triggers.onPush) {
1230
+ console.error(`maestro-orchestrator: drop push-gate-off project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
1214
1231
  return { ok: true, failures: [], durationMs: Date.now() - t0 }
1215
1232
  }
1216
1233
  // A push only re-reviews an MR that already has a completed review;
1217
1234
  // otherwise every newly opened MR would be reviewed twice.
1218
1235
  if (payload.trigger === 'push' && !(await hasCompletedReview(payload.projectId, payload.mrIid))) {
1236
+ console.error(`maestro-orchestrator: drop push-no-completed-history project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
1219
1237
  return { ok: true, failures: [], durationMs: Date.now() - t0 }
1220
1238
  }
1221
1239
  const { gitlabToken } = effective
1222
1240
  if (gitlabToken === undefined) {
1223
1241
  const message = `MR !${String(payload.mrIid)} for project ${payload.projectPath} has no GitLab token — set one in Maestro Settings or MAESTRO_GITLAB_TOKEN`
1224
- console.error(`maestro-orchestrator: ${message}`)
1242
+ console.error(`maestro-orchestrator: drop missing-token project=${payload.projectPath} mr=!${String(payload.mrIid)} trigger=${payload.trigger} — ${message}`)
1225
1243
  return { ok: false, failures: [message], durationMs: Date.now() - t0 }
1226
1244
  }
1227
1245
  const resolved = { ...effective, gitlabToken }
@@ -1307,7 +1325,7 @@ export function apply(ctx: Context, config: Config): void {
1307
1325
  : undefined
1308
1326
  await signals?.start()
1309
1327
  const postComment = async (body: string) => {
1310
- const response = await fetch(
1328
+ const response = await GitlabClient.fetchWithTimeout(
1311
1329
  `${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/notes`,
1312
1330
  {
1313
1331
  method: 'POST',
@@ -1318,7 +1336,7 @@ export function apply(ctx: Context, config: Config): void {
1318
1336
  if (!response.ok) throw new Error(`GitLab API error ${response.status}: ${await response.text()}`)
1319
1337
  }
1320
1338
  const replyToDiscussion = async (discussionId: string, body: string) => {
1321
- const response = await fetch(
1339
+ const response = await GitlabClient.fetchWithTimeout(
1322
1340
  `${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/discussions/${encodeURIComponent(discussionId)}/notes`,
1323
1341
  {
1324
1342
  method: 'POST',
@@ -1333,7 +1351,13 @@ export function apply(ctx: Context, config: Config): void {
1333
1351
  // CI-deep (spec §3) skips the decline and falls through to the clone
1334
1352
  // branch below; every other unmapped deep review still declines here.
1335
1353
  if (payload.mode === 'deep' && !shouldCiDeepReview(payload)) {
1336
- await declineUnmappedDeepReview(payload, { postComment, replyToDiscussion, writeFailedReport, gitlabBaseUrl: resolved.gitlabBaseUrl } as unknown as ReviewCommentDeps)
1354
+ const declined = await declineUnmappedDeepReview(payload, { postComment, replyToDiscussion, writeFailedReport, gitlabBaseUrl: resolved.gitlabBaseUrl } as unknown as ReviewCommentDeps)
1355
+ if (!declined) {
1356
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
1357
+ await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' })
1358
+ await signals?.finish('completed')
1359
+ return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 }
1360
+ }
1337
1361
  await recordReviewFinish(historyId, { status: 'completed', summary: 'Deep review declined (unmapped project)' })
1338
1362
  notifyTelegram('completed', 'Deep review declined (unmapped project)')
1339
1363
  await signals?.finish('completed')
@@ -1413,6 +1437,12 @@ export function apply(ctx: Context, config: Config): void {
1413
1437
  writeFailedReport,
1414
1438
  gitlabBaseUrl: resolved.gitlabBaseUrl,
1415
1439
  } as unknown as DiffOnlyReviewDeps)
1440
+ if (diffBody === '') {
1441
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
1442
+ await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' })
1443
+ await signals?.finish('completed')
1444
+ return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 }
1445
+ }
1416
1446
  const summary = summarize(diffBody)
1417
1447
  const branchNote = `fallback diff-only: branch ${payload.sourceBranch} not found on origin — ${summary ?? ''}`.trim()
1418
1448
  await recordReviewFinish(historyId, { status: 'completed', summary: branchNote })
@@ -1423,6 +1453,12 @@ export function apply(ctx: Context, config: Config): void {
1423
1453
  throw err
1424
1454
  }
1425
1455
  }
1456
+ if (fullBody === '') {
1457
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
1458
+ await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' })
1459
+ await signals?.finish('completed')
1460
+ return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 }
1461
+ }
1426
1462
  await recordReviewFinish(historyId, { status: 'completed', summary: summarize(fullBody) })
1427
1463
  notifyTelegram('completed', summarize(fullBody))
1428
1464
  await signals?.finish('completed')
@@ -64,15 +64,19 @@ export async function fetchMrSourceBranch(config: CiEnvConfig, fetcher: typeof f
64
64
  return (await fetchMrDetail(config, fetcher)).sourceBranch
65
65
  }
66
66
 
67
- /** MR detail pieces CI needs in one call: source branch (worktree) + head SHA (push-gate). */
68
- export async function fetchMrDetail(config: CiEnvConfig, fetcher: typeof fetch = fetch): Promise<{ sourceBranch: string; headSha: string }> {
67
+ /** MR detail pieces CI needs in one call: source branch (worktree) + head SHA (push-gate) + project path (comment header/link). */
68
+ export async function fetchMrDetail(config: CiEnvConfig, fetcher: typeof fetch = fetch): Promise<{ sourceBranch: string; headSha: string; projectPath: string }> {
69
69
  const url = `${config.gitlabBaseUrl}/api/v4/projects/${config.sourceProjectId}/merge_requests/${config.mrIid}`
70
70
  const res = await fetcher(url, { headers: gitlabAuthHeaders(config.gitlabToken) })
71
71
  if (!res.ok) throw new Error(`GitLab API error ${res.status}: ${await res.text()}`)
72
- const body = await res.json() as { source_branch?: string; sha?: string }
72
+ const body = await res.json() as { source_branch?: string; sha?: string; references?: { full?: string } }
73
73
  if (typeof body.source_branch !== 'string') throw new Error('GitLab merge request response is missing source_branch')
74
74
  if (typeof body.sha !== 'string') throw new Error('GitLab merge request response is missing sha')
75
- return { sourceBranch: body.source_branch, headSha: body.sha }
75
+ // references.full looks like "group/sub/project!123" — the real path feeds the
76
+ // comment header and View-MR link. Absent on old servers: fall back to project/<id>.
77
+ const full = body.references?.full
78
+ const projectPath = typeof full === 'string' && full.includes('!') ? full.slice(0, full.indexOf('!')) : `project/${config.sourceProjectId}`
79
+ return { sourceBranch: body.source_branch, headSha: body.sha, projectPath }
76
80
  }
77
81
 
78
82
  export async function runCiTrigger(
@@ -84,7 +88,7 @@ export async function runCiTrigger(
84
88
  history?: { lastCompletedReview(projectId: number, mrIid: number): Promise<{ headSha?: string } | undefined> }
85
89
  } = {},
86
90
  ): Promise<ReviewResult> {
87
- const { sourceBranch, headSha } = await fetchMrDetail(config, deps.fetcher)
91
+ const { sourceBranch, headSha, projectPath } = await fetchMrDetail(config, deps.fetcher)
88
92
  // Push-gate (mirror of the webhook autoRereviewOnPush semantics): the bridge fires
89
93
  // on every MR pipeline, so skip when this exact head SHA already completed — and
90
94
  // skip new pushes too unless REVIEW_ON_PUSH=1. A re-run then gets the H6 incremental
@@ -106,12 +110,12 @@ export async function runCiTrigger(
106
110
  } else if (await hasRunningEyes(coFetcher, config.gitlabBaseUrl, config.gitlabToken, config.sourceProjectId, config.mrIid)) {
107
111
  result = { ok: true, summary: 'another review is running — skipping', failures: [], durationMs: 0 }
108
112
  } else {
109
- // projectPath is synthetic (no webhook payload to read it from) — harmless: the
110
- // reviewer-ci profile's own projectMappings is always [], so orchestrator's
111
- // mapping lookup on projectPath never matches regardless of its exact value
112
- // (same precedent as the PR #52 runner it replaces).
113
+ // The reviewer-ci profile's own projectMappings is always [], so the
114
+ // orchestrator's mapping lookup on projectPath never matches regardless
115
+ // of its exact value — but the real path feeds the comment header and
116
+ // View-MR link, so prefer it over the synthetic project/<id> fallback.
113
117
  const request: ReviewRequest = {
114
- projectPath: `project/${config.sourceProjectId}`,
118
+ projectPath,
115
119
  projectId: config.sourceProjectId,
116
120
  mrIid: config.mrIid,
117
121
  sourceBranch,
@@ -4,7 +4,7 @@ import z from '@deepseek-ai/schemastery'
4
4
  import { loadUserConfig } from '../config-store.js'
5
5
  import { secretsMatch } from '../secure-compare.js'
6
6
  import type { MrOpenedPayload, ReviewRequest as OrchestratorReviewRequest } from '../events.js'
7
- import { routeGitlabReviewRequest } from '../review-intake.js'
7
+ import { describeDrop, routeGitlabReviewRequest } from '../review-intake.js'
8
8
  import type { ReviewProvider, ReviewRequest } from './interface.js'
9
9
 
10
10
  export const name = 'maestro-review-webhook'
@@ -127,10 +127,24 @@ export function apply(ctx: Context, config: Config): void {
127
127
  }
128
128
  let body: GitlabMrWebhookBody; try { body = JSON.parse(raw) } catch { res.writeHead(400).end(); return }
129
129
  const userConfig = await loadUserConfig()
130
- if ((body.object_kind === 'merge_request' || body.object_kind === 'note') && !hasValidGitlabMrIdentity(body)) { res.writeHead(400).end(); return }
131
- // The orchestrator is the sole push gate (resolveReviewTriggers); intake always emits.
132
- const request = routeGitlabReviewRequest(body, userConfig.botUsername ?? config.botUsername ?? 'maestro', { pushEnabled: true })
133
- if (request !== undefined) ctx.emit('maestro/review-request', request)
130
+ const botUsername = userConfig.botUsername ?? config.botUsername ?? 'maestro'
131
+ if ((body.object_kind === 'merge_request' || body.object_kind === 'note') && !hasValidGitlabMrIdentity(body)) {
132
+ console.error(`maestro-review-webhook: drop invalid-identity object_kind=${(body as { object_kind?: unknown }).object_kind ?? 'unknown'}`)
133
+ res.writeHead(400).end(); return
134
+ }
135
+ // The orchestrator is the sole push gate (resolveReviewTriggers);
136
+ // intake always emits so per-project overrides keep working.
137
+ const request = routeGitlabReviewRequest(body, botUsername, { pushEnabled: true })
138
+ if (request === undefined) {
139
+ const reason = describeDrop(body, botUsername, { pushEnabled: true })
140
+ if (reason !== undefined) {
141
+ const project = (body as { project?: { path_with_namespace?: unknown } }).project
142
+ const source = (body as { object_attributes?: { iid?: unknown } }).object_attributes
143
+ console.error(`maestro-review-webhook: drop ${reason} project=${typeof project?.path_with_namespace === 'string' ? project.path_with_namespace : 'unknown'} mr=!${typeof source?.iid === 'number' ? source.iid : '?'}`)
144
+ }
145
+ } else {
146
+ ctx.emit('maestro/review-request', request)
147
+ }
134
148
  res.writeHead(200).end()
135
149
  })
136
150
  }