@ddtcorex/dsh-maestro-review 0.4.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 (76) hide show
  1. package/README.md +13 -0
  2. package/cordis.patch.yml +18 -0
  3. package/lib/ci-clone.d.ts +21 -0
  4. package/lib/ci-clone.d.ts.map +1 -0
  5. package/lib/ci-clone.js +35 -0
  6. package/lib/ci-clone.js.map +1 -0
  7. package/lib/ci-coexist.d.ts +11 -0
  8. package/lib/ci-coexist.d.ts.map +1 -0
  9. package/lib/ci-coexist.js +38 -0
  10. package/lib/ci-coexist.js.map +1 -0
  11. package/lib/config-store.d.ts +13 -6
  12. package/lib/config-store.d.ts.map +1 -1
  13. package/lib/config-store.js.map +1 -1
  14. package/lib/events.d.ts +27 -0
  15. package/lib/events.d.ts.map +1 -1
  16. package/lib/gitlab-auth.d.ts +11 -0
  17. package/lib/gitlab-auth.d.ts.map +1 -0
  18. package/lib/gitlab-auth.js +15 -0
  19. package/lib/gitlab-auth.js.map +1 -0
  20. package/lib/gitlab-client.d.ts +7 -0
  21. package/lib/gitlab-client.d.ts.map +1 -1
  22. package/lib/gitlab-client.js +23 -1
  23. package/lib/gitlab-client.js.map +1 -1
  24. package/lib/incremental.d.ts.map +1 -1
  25. package/lib/incremental.js +4 -2
  26. package/lib/incremental.js.map +1 -1
  27. package/lib/orchestrator.d.ts +56 -6
  28. package/lib/orchestrator.d.ts.map +1 -1
  29. package/lib/orchestrator.js +243 -68
  30. package/lib/orchestrator.js.map +1 -1
  31. package/lib/providers/ci-trigger.d.ts +44 -0
  32. package/lib/providers/ci-trigger.d.ts.map +1 -0
  33. package/lib/providers/ci-trigger.js +150 -0
  34. package/lib/providers/ci-trigger.js.map +1 -0
  35. package/lib/providers/gitlab.d.ts.map +1 -1
  36. package/lib/providers/gitlab.js +16 -3
  37. package/lib/providers/gitlab.js.map +1 -1
  38. package/lib/review-history.d.ts +2 -1
  39. package/lib/review-history.d.ts.map +1 -1
  40. package/lib/review-history.js +67 -40
  41. package/lib/review-history.js.map +1 -1
  42. package/lib/review-intake.d.ts +9 -0
  43. package/lib/review-intake.d.ts.map +1 -1
  44. package/lib/review-intake.js +34 -1
  45. package/lib/review-intake.js.map +1 -1
  46. package/lib/review-marker.d.ts +17 -0
  47. package/lib/review-marker.d.ts.map +1 -0
  48. package/lib/review-marker.js +23 -0
  49. package/lib/review-marker.js.map +1 -0
  50. package/lib/review-signals.d.ts.map +1 -1
  51. package/lib/review-signals.js +8 -6
  52. package/lib/review-signals.js.map +1 -1
  53. package/lib/settings-rpc.js +1 -1
  54. package/lib/settings-rpc.js.map +1 -1
  55. package/package.json +14 -9
  56. package/profiles/reviewer-ci/cordis.patch.yml +61 -0
  57. package/profiles/reviewer-ci/package.json +19 -0
  58. package/profiles/reviewer-ci/pnpm-lock.yaml +62 -0
  59. package/profiles/reviewer-ci/pnpm-workspace.yaml +12 -0
  60. package/src/host/ci-clone.ts +54 -0
  61. package/src/host/ci-coexist.ts +45 -0
  62. package/src/host/config-store.ts +14 -1
  63. package/src/host/events.ts +29 -0
  64. package/src/host/gitlab-auth.ts +13 -0
  65. package/src/host/gitlab-client.ts +23 -1
  66. package/src/host/incremental.ts +6 -4
  67. package/src/host/orchestrator.ts +247 -46
  68. package/src/host/providers/ci-trigger.ts +168 -0
  69. package/src/host/providers/gitlab.ts +19 -4
  70. package/src/host/review-history.ts +65 -35
  71. package/src/host/review-intake.ts +36 -1
  72. package/src/host/review-marker.ts +25 -0
  73. package/src/host/review-signals.ts +9 -6
  74. package/src/host/settings-rpc.ts +1 -1
  75. package/templates/reviewer-project.gitlab-ci.yml +90 -0
  76. package/templates/source-project.gitlab-ci.yml +41 -0
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/host/orchestrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/host/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -31,6 +31,9 @@ import { reviewDigestText } from './notify.js';
31
31
  import { loadedReviewProfile } from './skills-tool.js';
32
32
  import { gitlabProvider } from './providers/gitlab.js';
33
33
  import './events.js';
34
+ import { gitlabAuthHeaders } from './gitlab-auth.js';
35
+ import { reviewMarker, resolveFlow } from './review-marker.js';
36
+ import { cloneSourceRepo, defaultRun } from './ci-clone.js';
34
37
  // Provider-aware wrapper — orchestrator can run reviews via any ReviewProvider.
35
38
  // This keeps the GitLab-specific flow intact while allowing Phase C to add GitHub/Jira without modifying core logic.
36
39
  export async function runReviewWithProvider(provider, request) {
@@ -132,7 +135,8 @@ export function buildReviewComment(opts) {
132
135
  ? `\n\n<details>\n<summary>⚠️ Failed to post (${opts.failures.length})</summary>\n\n${opts.failures.map((f) => `- \`${f}\``).join('\n')}\n\n</details>`
133
136
  : '';
134
137
  const footer = `\n\n---\n\n<sub>Generated by Maestro · [View MR →](${mrUrl})</sub>`;
135
- return `${title}\n\n${metaLine}\n\n${scopeNote}${opts.summary}${findingsLine}${failuresBlock}${footer}`;
138
+ const markerLine = opts.marker === undefined ? '' : `\n\n${reviewMarker(opts.marker.sha, opts.marker.flow)}`;
139
+ return `${title}\n\n${metaLine}\n\n${scopeNote}${opts.summary}${findingsLine}${failuresBlock}${footer}${markerLine}`;
136
140
  }
137
141
  export function buildNotStartedComment(opts) {
138
142
  const mrUrl = `${opts.gitlabBaseUrl.replace(/\/$/, '')}/${opts.projectPath}/-/merge_requests/${opts.mrIid}`;
@@ -147,6 +151,7 @@ export function buildNotStartedComment(opts) {
147
151
  `---`,
148
152
  '',
149
153
  `<sub>Generated by Maestro · [View MR →](${mrUrl})</sub>`,
154
+ ...(opts.marker === undefined ? [] : [``, `${reviewMarker(opts.marker.sha, opts.marker.flow)}`]),
150
155
  ].join('\n');
151
156
  }
152
157
  export const name = 'maestro-orchestrator';
@@ -199,10 +204,12 @@ export function getTurnErrorMessage(handle) {
199
204
  }
200
205
  /**
201
206
  * Resolve the model to use for an automated review. Priority: per-project
202
- * override > global reviewModel > DSH default (`fallback`).
207
+ * override > global reviewModel (Maestro Settings) > row-config reviewModel
208
+ * (lets a headless profile such as reviewer-ci pin a model from env vars,
209
+ * where there is no Settings UI) > DSH default (`fallback`).
203
210
  */
204
- export function resolveReviewModel(userConfig, mapping, fallback) {
205
- const raw = mapping?.reviewModel ?? userConfig.reviewModel;
211
+ export function resolveReviewModel(userConfig, mapping, fallback, rowSelection) {
212
+ const raw = mapping?.reviewModel ?? userConfig.reviewModel ?? rowSelection;
206
213
  if (raw === undefined || raw === null)
207
214
  return fallback;
208
215
  return {
@@ -211,6 +218,13 @@ export function resolveReviewModel(userConfig, mapping, fallback) {
211
218
  ...(raw.reasoningEffort === undefined ? {} : { reasoningEffort: ReasoningEffortId(raw.reasoningEffort) }),
212
219
  };
213
220
  }
221
+ /** Effective auto-trigger flags: per-project row overrides global, unset inherits (design §4). */
222
+ export function resolveReviewTriggers(userConfig, mapping) {
223
+ return {
224
+ onPush: mapping?.rereviewOnPush ?? userConfig.autoRereviewOnPush ?? false,
225
+ onAssign: mapping?.reviewOnAssign ?? userConfig.autoReviewOnAssign ?? true,
226
+ };
227
+ }
214
228
  /** Compose a newly-created agent from the preset service owned by the root context. */
215
229
  export async function mountAgentPreset(agentPresets, agentCtx, id) {
216
230
  await agentPresets.mount(agentCtx, id);
@@ -321,7 +335,7 @@ function normalizedDiffPath(path) {
321
335
  export async function postReviewFindings(findings, config) {
322
336
  const fetcher = config.fetcher ?? fetch;
323
337
  const apiBase = `${config.baseUrl}/api/v4/projects/${config.projectId}/merge_requests/${config.mrIid}`;
324
- const headers = { 'PRIVATE-TOKEN': config.token, 'Content-Type': 'application/json' };
338
+ const headers = { ...gitlabAuthHeaders(config.token), 'Content-Type': 'application/json' };
325
339
  for (const finding of findings) {
326
340
  let response;
327
341
  const label = severityPrefix(finding.severity);
@@ -382,7 +396,8 @@ export async function postReviewFindings(findings, config) {
382
396
  const inFlightKeys = new Set();
383
397
  function reviewKey(payload) {
384
398
  const scope = payload.scope.kind === 'mr' ? 'mr' : `discussion:${payload.scope.discussionId}`;
385
- return `${payload.projectId}:${payload.mrIid}:${payload.mode}:${scope}`;
399
+ const sha = typeof payload.pushSha === 'string' && payload.pushSha !== '' ? `:${payload.pushSha}` : '';
400
+ return `${payload.projectId}:${payload.mrIid}:${payload.mode}:${scope}:${payload.trigger}${sha}`;
386
401
  }
387
402
  /**
388
403
  * Stable 8-char hex suffix of the review key, so distinct concurrent reviews
@@ -432,12 +447,66 @@ export function auditorOutputFromSession(session) {
432
447
  return finalAssistantOutput(events) ?? [];
433
448
  }
434
449
  /** Full review + performance audit; resolves to the comment body that was posted. */
450
+ /** Marker for CI-posted comments; webhook payloads carry no headSha and stay marker-free. */
451
+ function commentMarker(payload) {
452
+ if (payload.headSha === undefined)
453
+ return undefined;
454
+ return { sha: payload.headSha, flow: resolveFlow(payload.mode) };
455
+ }
456
+ /** CI-deep decision: deep mode + CI env + head SHA (spec §3). Mapping is checked by the caller. */
457
+ export function shouldCiDeepReview(payload) {
458
+ return payload.mode === 'deep'
459
+ && payload.headSha !== undefined
460
+ && process.env.SOURCE_PROJECT_ID !== undefined
461
+ && process.env.MR_IID !== undefined;
462
+ }
463
+ /** CI quick-with-profile decision: quick mode + non-generic profile + CI env
464
+ * + head SHA. Quick + generic/unset stays diff-only (no clone cost); a real
465
+ * profile opts into the clone branch reviewer-only (no auditor — quick never
466
+ * audits, see shouldAudit in runReviewAndAudit). Mapping is checked by the caller. */
467
+ export function shouldCiQuickProfileReview(payload) {
468
+ return payload.mode === 'quick'
469
+ && payload.reviewProfile !== undefined
470
+ && payload.reviewProfile !== 'generic'
471
+ && payload.headSha !== undefined
472
+ && process.env.SOURCE_PROJECT_ID !== undefined
473
+ && process.env.MR_IID !== undefined;
474
+ }
475
+ /** Auditor degrade for CI (no runtime env): a govard throw becomes reviewer-only, never a failed review. */
476
+ export function withAuditorDegrade(runAuditor) {
477
+ return async (worktreePath, payload) => {
478
+ try {
479
+ return await runAuditor(worktreePath, payload);
480
+ }
481
+ catch {
482
+ return 'Auditor skipped — no runtime environment in CI (reviewer-only review).';
483
+ }
484
+ };
485
+ }
486
+ /**
487
+ * Auditor instruction. The mapped flow keeps the full environment + test-suite
488
+ * workflow; the CI flow has no runtime, so the prompt countermands the
489
+ * auditor preset's environment steps and drops the Environment & Test Suite
490
+ * section entirely instead of reporting it "blocked".
491
+ */
492
+ export function buildAuditorPrompt(opts) {
493
+ if (!opts.staticOnly) {
494
+ return 'Audit this merge request\'s performance: bring up the environment, run the test suite, look for regressions, then write a Markdown report and tear the environment down.';
495
+ }
496
+ return 'Audit this merge request\'s performance from the static diff and checked-out code only. '
497
+ + 'No runtime environment exists in this container: ignore the auditor preset\'s environment steps '
498
+ + '(do not bring anything up, do not run the test suite, do not tear anything down). '
499
+ + 'Look for regressions by static analysis (diff, dependencies, query/shape risks), then write a Markdown report '
500
+ + 'and OMIT the Environment & Test Suite section entirely — never report it as blocked.';
501
+ }
435
502
  export async function runReviewAndAudit(payload, deps) {
436
503
  assertSafeId(payload.projectId, 'projectId');
437
504
  assertSafeId(payload.mrIid, 'mrIid');
438
505
  const key = reviewKey(payload);
439
- if (inFlightKeys.has(key))
506
+ if (inFlightKeys.has(key)) {
507
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`);
440
508
  return '';
509
+ }
441
510
  inFlightKeys.add(key);
442
511
  try {
443
512
  const worktreePath = await deps.ensureWorktree(deps.localRepoPath, payload.sourceBranch, payload.projectId, payload.mrIid, reviewKeyHash(payload));
@@ -468,6 +537,7 @@ export async function runReviewAndAudit(payload, deps) {
468
537
  summary: summaryText,
469
538
  failures,
470
539
  findings: { newCount, replyCount, severityCounts },
540
+ marker: commentMarker(payload),
471
541
  })
472
542
  : `## 🤖 Maestro Review\n\n**\`${payload.projectPath}\` !${payload.mrIid}** · ✅ Completed · \`${payload.mode}\`${deps.reviewProfile !== undefined ? ` · \`${deps.reviewProfile}\`` : ''}\n\n${summaryText}${failures.length > 0 ? `\n\n<details>\n<summary>⚠️ Failed to post (${failures.length})</summary>\n\n${failures.map((f) => `- \`${f}\``).join('\n')}\n\n</details>` : ''}`;
473
543
  sections.push(richOpts);
@@ -489,7 +559,8 @@ export async function runReviewAndAudit(payload, deps) {
489
559
  else
490
560
  await deps.postComment(body);
491
561
  }
492
- catch {
562
+ catch (err) {
563
+ console.error(`maestro-orchestrator: posting review comment failed: ${err instanceof Error ? err.message : String(err)}`);
493
564
  await deps.writeFailedReport(payload.mrIid, body);
494
565
  }
495
566
  return body;
@@ -512,8 +583,10 @@ export async function runDiffOnlyReview(payload, deps) {
512
583
  assertSafeId(payload.projectId, 'projectId');
513
584
  assertSafeId(payload.mrIid, 'mrIid');
514
585
  const key = reviewKey(payload);
515
- if (inFlightKeys.has(key))
586
+ if (inFlightKeys.has(key)) {
587
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`);
516
588
  return '';
589
+ }
517
590
  inFlightKeys.add(key);
518
591
  try {
519
592
  const { summary, failures } = await deps.runReviewer(payload);
@@ -526,6 +599,7 @@ export async function runDiffOnlyReview(payload, deps) {
526
599
  summary: summary ?? '',
527
600
  failures,
528
601
  isDiffOnly: true,
602
+ marker: commentMarker(payload),
529
603
  })
530
604
  : `## 🤖 Maestro Review — Diff-only\n\n> **Scope:** Diff-only — reviewed the GitLab diff without a local checkout, Magento environment, static analysis, or tests. For a full review, add this project in Settings → Maestro and mention again.\n\n${summary}${failures.length > 0 ? `\n\n<details>\n<summary>⚠️ Failed to post (${failures.length})</summary>\n\n${failures.map((f) => `- \`${f}\``).join('\n')}\n\n</details>` : ''}`;
531
605
  const body = diffBody;
@@ -535,7 +609,8 @@ export async function runDiffOnlyReview(payload, deps) {
535
609
  else
536
610
  await deps.postComment(body);
537
611
  }
538
- catch {
612
+ catch (err) {
613
+ console.error(`maestro-orchestrator: posting review comment failed: ${err instanceof Error ? err.message : String(err)}`);
539
614
  await deps.writeFailedReport(payload.mrIid, body);
540
615
  }
541
616
  return body;
@@ -544,18 +619,23 @@ export async function runDiffOnlyReview(payload, deps) {
544
619
  inFlightKeys.delete(key);
545
620
  }
546
621
  }
547
- /** Decline a Deep request that lacks the local mapping it requires. */
622
+ /** Decline a Deep request that lacks the local mapping it requires.
623
+ * Resolves `true` when the decline was posted, `false` when a duplicate
624
+ * in-flight review is already handling this key (caller must not record a
625
+ * completion for work it did not do). */
548
626
  export async function declineUnmappedDeepReview(payload, deps) {
549
627
  assertSafeId(payload.projectId, 'projectId');
550
628
  assertSafeId(payload.mrIid, 'mrIid');
551
629
  const key = reviewKey(payload);
552
- if (inFlightKeys.has(key))
553
- return;
630
+ if (inFlightKeys.has(key)) {
631
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`);
632
+ return false;
633
+ }
554
634
  inFlightKeys.add(key);
555
635
  const depsWithUrl = deps;
556
636
  const baseUrl = depsWithUrl.gitlabBaseUrl;
557
637
  const body = baseUrl !== undefined
558
- ? buildNotStartedComment({ gitlabBaseUrl: baseUrl, projectPath: payload.projectPath, mrIid: payload.mrIid })
638
+ ? buildNotStartedComment({ gitlabBaseUrl: baseUrl, projectPath: payload.projectPath, mrIid: payload.mrIid, marker: commentMarker(payload) })
559
639
  : '## 🤖 Maestro Review — Not started\n\n**`' + payload.projectPath + '` !' + payload.mrIid + '** · ⏸️ Not started\n\n> Deep review requires a project mapping with a local checkout and Magento environment.\n> Add this project in **Settings → Maestro**, then mention the reviewer again.';
560
640
  try {
561
641
  try {
@@ -564,9 +644,11 @@ export async function declineUnmappedDeepReview(payload, deps) {
564
644
  else
565
645
  await deps.postComment(body);
566
646
  }
567
- catch {
647
+ catch (err) {
648
+ console.error(`maestro-orchestrator: posting review comment failed: ${err instanceof Error ? err.message : String(err)}`);
568
649
  await deps.writeFailedReport(payload.mrIid, body);
569
650
  }
651
+ return true;
570
652
  }
571
653
  finally {
572
654
  inFlightKeys.delete(key);
@@ -626,7 +708,7 @@ export function govardWorktreeOverride(projectId, mrIid, keySuffix) {
626
708
  */
627
709
  export async function fetchMrBaseSha(baseUrl, token, projectId, mrIid, fetcher = fetch) {
628
710
  try {
629
- const response = await fetcher(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}`, { headers: { 'PRIVATE-TOKEN': token } });
711
+ const response = await fetcher(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}`, { headers: gitlabAuthHeaders(token) });
630
712
  if (!response.ok)
631
713
  return undefined;
632
714
  const mr = await response.json();
@@ -942,7 +1024,7 @@ export function apply(ctx, config) {
942
1024
  throw err;
943
1025
  }
944
1026
  }
945
- async function runAuditor(worktreePath, payload, effective, modelSelection) {
1027
+ async function runAuditor(worktreePath, payload, effective, modelSelection, opts) {
946
1028
  let handle;
947
1029
  const agentOptions = agentOptionsForModel(modelSelection ?? ctx.agentDefaultModel.currentSelection());
948
1030
  try {
@@ -970,7 +1052,7 @@ export function apply(ctx, config) {
970
1052
  }
971
1053
  ctx.sessionTitle.rename(handle.agent.session, `Maestro Auditor — MR !${payload.mrIid} (${payload.projectPath})`);
972
1054
  try {
973
- const prompt = 'Audit this merge request\'s performance: bring up the environment, run the test suite, look for regressions, then write a Markdown report and tear the environment down.';
1055
+ const prompt = buildAuditorPrompt({ staticOnly: opts?.staticOnly === true });
974
1056
  handle.agent.followup(createUserMessage({ content: [{ type: 'text', text: prompt }], source: { kind: 'user' } }));
975
1057
  await whenIdleWithTimeout(handle, effectiveAgentTimeoutMs);
976
1058
  const output = auditorOutputFromSession(handle.agent.session);
@@ -981,8 +1063,9 @@ export function apply(ctx, config) {
981
1063
  await handle.dispose();
982
1064
  }
983
1065
  }
984
- ctx.on('maestro/review-request', (payload) => {
985
- void (async () => {
1066
+ async function runReview(payload) {
1067
+ const t0 = Date.now();
1068
+ try {
986
1069
  const userConfig = await loadUserConfig();
987
1070
  const effective = {
988
1071
  gitlabBaseUrl: userConfig.gitlabBaseUrl ?? config.gitlabBaseUrl,
@@ -1000,18 +1083,41 @@ export function apply(ctx, config) {
1000
1083
  });
1001
1084
  }
1002
1085
  const mapping = effective.projectMappings.find(m => m.projectPath === payload.projectPath);
1086
+ // CI-deep (spec §3): unmapped deep review with CI env + head SHA skips
1087
+ // both the decline and the diff-only fallback and runs the clone branch
1088
+ // below, which shares the mapped path's completion tail.
1089
+ const ciDeep = mapping === undefined && payload.mode === 'deep' && shouldCiDeepReview(payload);
1090
+ // CI quick-with-profile: unmapped quick + non-generic profile + CI env
1091
+ // skips the diff-only fallback and joins the clone branch below, which
1092
+ // runs reviewer-only (quick never audits).
1093
+ const ciQuickProfile = mapping === undefined && shouldCiQuickProfileReview(payload);
1003
1094
  // Unmapped reviewer assignments remain no-ops. Only an explicit mention
1004
1095
  // may opt into the intentionally limited, diff-only fallback below.
1005
- if (mapping === undefined && payload.trigger !== 'mention')
1006
- return;
1096
+ if (mapping === undefined && payload.trigger !== 'mention') {
1097
+ console.error(`maestro-orchestrator: drop unmapped project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`);
1098
+ return { ok: true, failures: [], durationMs: Date.now() - t0 };
1099
+ }
1100
+ const triggers = resolveReviewTriggers(userConfig, mapping);
1101
+ // Gated-off auto-triggers stay fully silent: no history, no signals, no comment (host log only).
1102
+ if (payload.trigger === 'reviewer-assignment' && !triggers.onAssign) {
1103
+ console.error(`maestro-orchestrator: drop assign-gate-off project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`);
1104
+ return { ok: true, failures: [], durationMs: Date.now() - t0 };
1105
+ }
1106
+ if (payload.trigger === 'push' && !triggers.onPush) {
1107
+ console.error(`maestro-orchestrator: drop push-gate-off project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`);
1108
+ return { ok: true, failures: [], durationMs: Date.now() - t0 };
1109
+ }
1007
1110
  // A push only re-reviews an MR that already has a completed review;
1008
1111
  // otherwise every newly opened MR would be reviewed twice.
1009
- if (payload.trigger === 'push' && !(await hasCompletedReview(payload.projectId, payload.mrIid)))
1010
- return;
1112
+ if (payload.trigger === 'push' && !(await hasCompletedReview(payload.projectId, payload.mrIid))) {
1113
+ console.error(`maestro-orchestrator: drop push-no-completed-history project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`);
1114
+ return { ok: true, failures: [], durationMs: Date.now() - t0 };
1115
+ }
1011
1116
  const { gitlabToken } = effective;
1012
1117
  if (gitlabToken === undefined) {
1013
- console.error(`maestro-orchestrator: MR !${String(payload.mrIid)} for project ${payload.projectPath} has no GitLab token — set one in Maestro Settings or MAESTRO_GITLAB_TOKEN`);
1014
- return;
1118
+ const message = `MR !${String(payload.mrIid)} for project ${payload.projectPath} has no GitLab token — set one in Maestro Settings or MAESTRO_GITLAB_TOKEN`;
1119
+ console.error(`maestro-orchestrator: drop missing-token project=${payload.projectPath} mr=!${String(payload.mrIid)} trigger=${payload.trigger} — ${message}`);
1120
+ return { ok: false, failures: [message], durationMs: Date.now() - t0 };
1015
1121
  }
1016
1122
  const resolved = { ...effective, gitlabToken };
1017
1123
  const historyId = `${payload.projectId}-${payload.mrIid}-${Date.now()}`;
@@ -1043,7 +1149,7 @@ export function apply(ctx, config) {
1043
1149
  const fallbackSelection = ctx.get?.('agentDefaultModel')?.currentSelection()
1044
1150
  ?? ctx.agentDefaultModel?.currentSelection()
1045
1151
  ?? { provider: 'fallback', model: 'fallback' };
1046
- const reviewModelSelection = resolveReviewModel(userConfig, mapping, fallbackSelection);
1152
+ const reviewModelSelection = resolveReviewModel(userConfig, mapping, fallbackSelection, config.reviewModel);
1047
1153
  // Opt-in Telegram digest; a delivery failure is logged and dropped.
1048
1154
  const reviewStartMsOuter = Date.now();
1049
1155
  const notifyTelegram = (status, summary, extra) => {
@@ -1093,34 +1199,42 @@ export function apply(ctx, config) {
1093
1199
  : undefined;
1094
1200
  await signals?.start();
1095
1201
  const postComment = async (body) => {
1096
- const response = await fetch(`${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/notes`, {
1202
+ const response = await GitlabClient.fetchWithTimeout(`${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/notes`, {
1097
1203
  method: 'POST',
1098
- headers: { 'PRIVATE-TOKEN': resolved.gitlabToken, 'Content-Type': 'application/json' },
1204
+ headers: { ...gitlabAuthHeaders(resolved.gitlabToken), 'Content-Type': 'application/json' },
1099
1205
  body: JSON.stringify({ body }),
1100
1206
  });
1101
1207
  if (!response.ok)
1102
1208
  throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
1103
1209
  };
1104
1210
  const replyToDiscussion = async (discussionId, body) => {
1105
- const response = await fetch(`${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/discussions/${encodeURIComponent(discussionId)}/notes`, {
1211
+ const response = await GitlabClient.fetchWithTimeout(`${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/discussions/${encodeURIComponent(discussionId)}/notes`, {
1106
1212
  method: 'POST',
1107
- headers: { 'PRIVATE-TOKEN': resolved.gitlabToken, 'Content-Type': 'application/json' },
1213
+ headers: { ...gitlabAuthHeaders(resolved.gitlabToken), 'Content-Type': 'application/json' },
1108
1214
  body: JSON.stringify({ body }),
1109
1215
  });
1110
1216
  if (!response.ok)
1111
1217
  throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
1112
1218
  };
1113
1219
  try {
1114
- if (mapping === undefined) {
1115
- if (payload.mode === 'deep') {
1116
- await declineUnmappedDeepReview(payload, { postComment, replyToDiscussion, writeFailedReport, gitlabBaseUrl: resolved.gitlabBaseUrl });
1220
+ if (mapping === undefined && !ciDeep && !ciQuickProfile) {
1221
+ // CI-deep (spec §3) skips the decline and falls through to the clone
1222
+ // branch below; every other unmapped deep review still declines here.
1223
+ if (payload.mode === 'deep' && !shouldCiDeepReview(payload)) {
1224
+ const declined = await declineUnmappedDeepReview(payload, { postComment, replyToDiscussion, writeFailedReport, gitlabBaseUrl: resolved.gitlabBaseUrl });
1225
+ if (!declined) {
1226
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`);
1227
+ await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' });
1228
+ await signals?.finish('completed');
1229
+ return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 };
1230
+ }
1117
1231
  await recordReviewFinish(historyId, { status: 'completed', summary: 'Deep review declined (unmapped project)' });
1118
1232
  notifyTelegram('completed', 'Deep review declined (unmapped project)');
1119
1233
  await signals?.finish('completed');
1120
- return;
1234
+ return { ok: true, summary: 'Deep review declined (unmapped project)', failures: [], durationMs: Date.now() - t0 };
1121
1235
  }
1122
1236
  const diffBody = await runDiffOnlyReview(payload, {
1123
- runReviewer: (p) => runReviewer(undefined, p, resolved, undefined, reviewModelSelection, incrementalBlock),
1237
+ runReviewer: (p) => runReviewer(undefined, p, resolved, payload.reviewProfile, reviewModelSelection, incrementalBlock),
1124
1238
  postComment,
1125
1239
  replyToDiscussion,
1126
1240
  writeFailedReport,
@@ -1129,59 +1243,120 @@ export function apply(ctx, config) {
1129
1243
  await recordReviewFinish(historyId, { status: 'completed', summary: summarize(diffBody) });
1130
1244
  notifyTelegram('completed', summarize(diffBody));
1131
1245
  await signals?.finish('completed');
1132
- return;
1246
+ return { ok: true, summary: summarize(diffBody), failures: [], durationMs: Date.now() - t0 };
1133
1247
  }
1134
1248
  let fullBody;
1135
- try {
1136
- fullBody = await runReviewAndAudit(payload, {
1137
- localRepoPath: mapping.localRepoPath,
1138
- ensureWorktree,
1139
- removeWorktree,
1140
- runReviewer: (worktreePath, p) => runReviewer(worktreePath, p, resolved, mapping.reviewProfile ?? 'magento2', reviewModelSelection, incrementalBlock),
1141
- runAuditor: (worktreePath, p) => runAuditor(worktreePath, p, resolved, reviewModelSelection),
1142
- postComment,
1143
- replyToDiscussion,
1144
- writeFailedReport,
1145
- gitlabBaseUrl: resolved.gitlabBaseUrl,
1146
- reviewProfile: mapping.reviewProfile ?? 'magento2',
1147
- });
1249
+ if (ciDeep || ciQuickProfile) {
1250
+ // CI-deep (mapping is always undefined here — the unmapped block above
1251
+ // returned for every other case): clone the source at the head SHA,
1252
+ // map it in memory, and reuse the mapped machinery reviewer-only.
1253
+ // CI quick-with-profile joins the same branch; runReviewAndAudit skips
1254
+ // the auditor for quick (shouldAudit), so it stays reviewer-only.
1255
+ // No govard/vendor linking (ciEnsureWorktree is plain fetch + worktree).
1256
+ const ciHost = process.env.GITLAB_HOST?.trim() || new URL(resolved.gitlabBaseUrl).hostname;
1257
+ const cloneDir = join('/tmp', `maestro-ci-src-${payload.projectId}-${payload.mrIid}`);
1258
+ await cloneSourceRepo({ fetcher: fetch, run: defaultRun, host: ciHost, projectId: payload.projectId, sourceBranch: payload.sourceBranch, headSha: payload.headSha, token: resolved.gitlabToken, dir: cloneDir });
1259
+ try {
1260
+ const ciEnsureWorktree = async (repoPath, branch, pid, iid, suffix) => {
1261
+ assertSafeBranchName(branch);
1262
+ const wt = join('/tmp', `maestro-mr-${pid}-${iid}${suffix === undefined ? '' : `-${suffix}`}`);
1263
+ await defaultRun('git', ['fetch', '--depth', '50', 'origin', branch], repoPath);
1264
+ await defaultRun('git', ['worktree', 'remove', '--force', wt], repoPath).catch(() => { });
1265
+ await defaultRun('git', ['worktree', 'add', '--detach', '--', wt, payload.headSha], repoPath);
1266
+ return wt;
1267
+ };
1268
+ fullBody = await runReviewAndAudit(payload, {
1269
+ localRepoPath: cloneDir,
1270
+ ensureWorktree: ciEnsureWorktree,
1271
+ removeWorktree,
1272
+ runReviewer: (worktreePath, p) => runReviewer(worktreePath, p, resolved, payload.reviewProfile ?? 'generic', reviewModelSelection, incrementalBlock),
1273
+ runAuditor: withAuditorDegrade((worktreePath, p) => runAuditor(worktreePath, p, resolved, reviewModelSelection, { staticOnly: true })),
1274
+ postComment,
1275
+ replyToDiscussion,
1276
+ writeFailedReport,
1277
+ gitlabBaseUrl: resolved.gitlabBaseUrl,
1278
+ reviewProfile: payload.reviewProfile ?? 'generic',
1279
+ });
1280
+ }
1281
+ finally {
1282
+ await defaultRun('rm', ['-rf', cloneDir]).catch(() => { });
1283
+ }
1148
1284
  }
1149
- catch (err) {
1150
- const isBranchNotFound = err?.code === 'BRANCH_NOT_FOUND' || isBranchNotFoundError(err);
1151
- if (isBranchNotFound) {
1152
- const diffBody = await runDiffOnlyReview(payload, {
1153
- runReviewer: (p) => runReviewer(undefined, p, resolved, undefined, reviewModelSelection, incrementalBlock),
1285
+ else {
1286
+ // Unreachable when mapping is undefined: the unmapped block returned
1287
+ // for every non-CI-deep case, and ciDeep took the branch above.
1288
+ if (mapping === undefined)
1289
+ throw new Error('unreachable: unmapped review without CI-deep decision');
1290
+ try {
1291
+ fullBody = await runReviewAndAudit(payload, {
1292
+ localRepoPath: mapping.localRepoPath,
1293
+ ensureWorktree,
1294
+ removeWorktree,
1295
+ runReviewer: (worktreePath, p) => runReviewer(worktreePath, p, resolved, mapping.reviewProfile ?? 'magento2', reviewModelSelection, incrementalBlock),
1296
+ runAuditor: (worktreePath, p) => runAuditor(worktreePath, p, resolved, reviewModelSelection),
1154
1297
  postComment,
1155
1298
  replyToDiscussion,
1156
1299
  writeFailedReport,
1157
1300
  gitlabBaseUrl: resolved.gitlabBaseUrl,
1301
+ reviewProfile: mapping.reviewProfile ?? 'magento2',
1158
1302
  });
1159
- const summary = summarize(diffBody);
1160
- const branchNote = `fallback diff-only: branch ${payload.sourceBranch} not found on origin — ${summary ?? ''}`.trim();
1161
- await recordReviewFinish(historyId, { status: 'completed', summary: branchNote });
1162
- notifyTelegram('completed', branchNote);
1163
- await signals?.finish('completed');
1164
- return;
1165
1303
  }
1166
- throw err;
1304
+ catch (err) {
1305
+ const isBranchNotFound = err?.code === 'BRANCH_NOT_FOUND' || isBranchNotFoundError(err);
1306
+ if (isBranchNotFound) {
1307
+ const diffBody = await runDiffOnlyReview(payload, {
1308
+ runReviewer: (p) => runReviewer(undefined, p, resolved, payload.reviewProfile, reviewModelSelection, incrementalBlock),
1309
+ postComment,
1310
+ replyToDiscussion,
1311
+ writeFailedReport,
1312
+ gitlabBaseUrl: resolved.gitlabBaseUrl,
1313
+ });
1314
+ if (diffBody === '') {
1315
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`);
1316
+ await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' });
1317
+ await signals?.finish('completed');
1318
+ return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 };
1319
+ }
1320
+ const summary = summarize(diffBody);
1321
+ const branchNote = `fallback diff-only: branch ${payload.sourceBranch} not found on origin — ${summary ?? ''}`.trim();
1322
+ await recordReviewFinish(historyId, { status: 'completed', summary: branchNote });
1323
+ notifyTelegram('completed', branchNote);
1324
+ await signals?.finish('completed');
1325
+ return { ok: true, summary: branchNote, failures: [], durationMs: Date.now() - t0 };
1326
+ }
1327
+ throw err;
1328
+ }
1329
+ }
1330
+ if (fullBody === '') {
1331
+ console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`);
1332
+ await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' });
1333
+ await signals?.finish('completed');
1334
+ return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 };
1167
1335
  }
1168
1336
  await recordReviewFinish(historyId, { status: 'completed', summary: summarize(fullBody) });
1169
1337
  notifyTelegram('completed', summarize(fullBody));
1170
1338
  await signals?.finish('completed');
1339
+ return { ok: true, summary: summarize(fullBody), failures: [], durationMs: Date.now() - t0 };
1171
1340
  }
1172
1341
  catch (err) {
1173
1342
  const message = err instanceof Error ? err.message : String(err);
1174
1343
  await recordReviewFinish(historyId, { status: 'failed', error: message }).catch(() => { });
1175
1344
  notifyTelegram('failed', message);
1176
1345
  await signals?.finish('failed');
1177
- throw err;
1346
+ return { ok: false, summary: undefined, failures: [message], durationMs: Date.now() - t0 };
1178
1347
  }
1179
- })().catch((err) => {
1348
+ }
1349
+ catch (err) {
1180
1350
  // Worktree creation, agent creation, and fallback delivery all run from
1181
- // an event callback, so surface failures rather than leaking a rejected
1182
- // fire-and-forget Promise.
1351
+ // this function — surface failures as a result instead of an unhandled
1352
+ // rejection, so both the fire-and-forget webhook path and an awaiting
1353
+ // CI caller observe the same outcome.
1354
+ const message = err instanceof Error ? err.message : String(err);
1183
1355
  console.error(`maestro-orchestrator: review run failed for MR !${String(payload.mrIid)}:`, err);
1184
- });
1185
- });
1356
+ return { ok: false, summary: undefined, failures: [message], durationMs: Date.now() - t0 };
1357
+ }
1358
+ }
1359
+ ctx.on('maestro/review-request', (payload) => { void runReview(payload); });
1360
+ ctx.provide('reviewRunner', runReview);
1186
1361
  }
1187
1362
  //# sourceMappingURL=orchestrator.js.map