@debugg-ai/debugg-ai-mcp 3.7.4 → 3.8.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.
@@ -20,6 +20,7 @@ import { probeLocalPort, probeTunnelHealth } from '../utils/localReachability.js
20
20
  import { extractLocalhostPort } from '../utils/urlParser.js';
21
21
  import { resolveTargetUrl, buildContext, findExistingTunnel, ensureTunnel, sanitizeResponseUrls, touchTunnelById, } from '../utils/tunnelContext.js';
22
22
  import { getCachedTemplateUuid, invalidateTemplateCache } from '../utils/handlerCaches.js';
23
+ import { detectLocalGitRef } from '../utils/gitContext.js';
23
24
  import { getCrawlTemplateSlug } from '../services/workflows.js';
24
25
  import { isTransientWorkflowError, transientReasonTag } from '../utils/transientErrors.js';
25
26
  import { Telemetry, TelemetryEvents } from '../utils/telemetry.js';
@@ -179,6 +180,18 @@ export async function triggerCrawlHandler(input, context, rawProgressCallback) {
179
180
  contextData.headless = true; // D7: the MCP always runs headless — no opt-out.
180
181
  if (typeof input.timeoutSeconds === 'number')
181
182
  contextData.timeoutSeconds = input.timeoutSeconds;
183
+ // sentinal-lwtaw.13 (MCP side): the TRIGGER POINT owns the git fact. Attach
184
+ // the LOCAL checkout's branch + commit so the backend mints a git-backed
185
+ // Atlas version for this crawl — SAME snake_case contextData keys the
186
+ // PR-webhook path reads (commit_sha, branch). Best-effort + non-fatal:
187
+ // detectLocalGitRef never throws and a non-git target attaches nothing
188
+ // (honest no-git) and still crawls. Keys are set ONLY when present so we
189
+ // never fabricate a ref.
190
+ const gitRef = await detectLocalGitRef();
191
+ if (gitRef.commitSha)
192
+ contextData.commit_sha = gitRef.commitSha;
193
+ if (gitRef.branch)
194
+ contextData.branch = gitRef.branch;
182
195
  const env = {};
183
196
  if (input.environmentId)
184
197
  env.environmentId = input.environmentId;
@@ -3,6 +3,9 @@
3
3
  * Parses the origin remote URL into "owner/repo" format.
4
4
  */
5
5
  import { execSync } from 'child_process';
6
+ import { ProjectAnalyzer } from './projectAnalyzer.js';
7
+ import { Logger } from './logger.js';
8
+ const logger = new Logger({ module: 'gitContext' });
6
9
  let cached; // undefined = not yet checked
7
10
  /**
8
11
  * Detect the repo name (e.g. "debugg-ai/debugg-ai-frontend") from git remote origin.
@@ -25,6 +28,29 @@ export function detectRepoName() {
25
28
  }
26
29
  return cached;
27
30
  }
31
+ /**
32
+ * Detect the LOCAL git ref (branch + commit sha) from the current working
33
+ * directory — the repo whose dev server the caller is crawling.
34
+ *
35
+ * sentinal-lwtaw.13 (MCP side): the TRIGGER POINT owns the git fact. The
36
+ * environment says WHERE to crawl; the caller supplies the ref it's running so
37
+ * the backend can mint a git-backed Atlas version. Delegates to
38
+ * ProjectAnalyzer's existing `.git/HEAD` readers — no new git parsing.
39
+ *
40
+ * Best-effort by contract: returns `{}` when cwd isn't a git repo (or the read
41
+ * fails). NEVER throws and NEVER fabricates a branch/sha — a git-less target
42
+ * must still crawl (honest no-git). NOT cached (unlike detectRepoName): the
43
+ * branch/commit change under a long-lived MCP process, so each crawl re-reads.
44
+ */
45
+ export async function detectLocalGitRef() {
46
+ try {
47
+ return await new ProjectAnalyzer().getGitRef(process.cwd());
48
+ }
49
+ catch (err) {
50
+ logger.debug('Could not determine local git ref', err);
51
+ return {};
52
+ }
53
+ }
28
54
  /**
29
55
  * Parse an origin URL into "owner/repo" format.
30
56
  * Handles SSH (git@github.com:owner/repo.git) and HTTPS (https://github.com/owner/repo.git).
@@ -438,6 +438,29 @@ export class ProjectAnalyzer {
438
438
  extractRepoName(projectPath) {
439
439
  return projectPath.split('/').pop() || 'unknown';
440
440
  }
441
+ /**
442
+ * Best-effort local git ref (branch + full commit sha) for a project dir.
443
+ *
444
+ * Reuses the existing `.git/HEAD` readers (getCurrentBranch /
445
+ * getCurrentCommitHash) — no new git parsing. NEVER throws and NEVER
446
+ * fabricates: a non-git dir (or any read failure) yields `{}` so a git-less
447
+ * crawl target still crawls (honest no-git). Not cached — a long-lived MCP
448
+ * process must re-read after the caller checks out a branch or commits.
449
+ */
450
+ async getGitRef(repoPath) {
451
+ const projectPath = repoPath || process.cwd();
452
+ try {
453
+ const [branch, commitSha] = await Promise.all([
454
+ this.getCurrentBranch(projectPath),
455
+ this.getCurrentCommitHash(projectPath),
456
+ ]);
457
+ return { branch, commitSha };
458
+ }
459
+ catch (error) {
460
+ logger.debug('Could not determine local git ref', error);
461
+ return {};
462
+ }
463
+ }
441
464
  /**
442
465
  * Get current git branch (simplified)
443
466
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugg-ai/debugg-ai-mcp",
3
- "version": "3.7.4",
3
+ "version": "3.8.0",
4
4
  "description": "Zero-Config, Fully AI-Managed End-to-End Testing for all code gen platforms.",
5
5
  "type": "module",
6
6
  "bin": {