codeloop-mcp-server 0.1.91 → 0.1.96

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 (82) hide show
  1. package/README.md +30 -0
  2. package/dist/evidence/binary_freshness.d.ts +27 -0
  3. package/dist/evidence/binary_freshness.d.ts.map +1 -1
  4. package/dist/evidence/binary_freshness.js +100 -22
  5. package/dist/evidence/binary_freshness.js.map +1 -1
  6. package/dist/evidence/change_coverage.d.ts +41 -0
  7. package/dist/evidence/change_coverage.d.ts.map +1 -1
  8. package/dist/evidence/change_coverage.js +69 -2
  9. package/dist/evidence/change_coverage.js.map +1 -1
  10. package/dist/evidence/interaction_evidence.d.ts +38 -0
  11. package/dist/evidence/interaction_evidence.d.ts.map +1 -1
  12. package/dist/evidence/interaction_evidence.js +60 -0
  13. package/dist/evidence/interaction_evidence.js.map +1 -1
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +80 -5
  17. package/dist/index.js.map +1 -1
  18. package/dist/runners/android_sdk.d.ts +50 -0
  19. package/dist/runners/android_sdk.d.ts.map +1 -0
  20. package/dist/runners/android_sdk.js +123 -0
  21. package/dist/runners/android_sdk.js.map +1 -0
  22. package/dist/runners/app_launcher.d.ts +22 -0
  23. package/dist/runners/app_launcher.d.ts.map +1 -1
  24. package/dist/runners/app_launcher.js +70 -18
  25. package/dist/runners/app_launcher.js.map +1 -1
  26. package/dist/runners/device_probe.d.ts.map +1 -1
  27. package/dist/runners/device_probe.js +5 -2
  28. package/dist/runners/device_probe.js.map +1 -1
  29. package/dist/runners/interaction_engine.js +7 -0
  30. package/dist/runners/interaction_engine.js.map +1 -1
  31. package/dist/runners/journey_to_maestro.d.ts +27 -0
  32. package/dist/runners/journey_to_maestro.d.ts.map +1 -1
  33. package/dist/runners/journey_to_maestro.js +54 -0
  34. package/dist/runners/journey_to_maestro.js.map +1 -1
  35. package/dist/runners/logging_readiness.d.ts.map +1 -1
  36. package/dist/runners/logging_readiness.js +38 -7
  37. package/dist/runners/logging_readiness.js.map +1 -1
  38. package/dist/runners/modal_detector.d.ts +13 -0
  39. package/dist/runners/modal_detector.d.ts.map +1 -1
  40. package/dist/runners/modal_detector.js +101 -2
  41. package/dist/runners/modal_detector.js.map +1 -1
  42. package/dist/runners/screenshot.d.ts.map +1 -1
  43. package/dist/runners/screenshot.js +10 -1
  44. package/dist/runners/screenshot.js.map +1 -1
  45. package/dist/runners/semantics_audit.d.ts +32 -0
  46. package/dist/runners/semantics_audit.d.ts.map +1 -0
  47. package/dist/runners/semantics_audit.js +140 -0
  48. package/dist/runners/semantics_audit.js.map +1 -0
  49. package/dist/runners/uia_resolver.d.ts.map +1 -1
  50. package/dist/runners/uia_resolver.js +32 -0
  51. package/dist/runners/uia_resolver.js.map +1 -1
  52. package/dist/runners/video_recorder.d.ts.map +1 -1
  53. package/dist/runners/video_recorder.js +25 -6
  54. package/dist/runners/video_recorder.js.map +1 -1
  55. package/dist/runners/wayland.d.ts +32 -0
  56. package/dist/runners/wayland.d.ts.map +1 -0
  57. package/dist/runners/wayland.js +49 -0
  58. package/dist/runners/wayland.js.map +1 -0
  59. package/dist/runners/window_manager.d.ts +23 -0
  60. package/dist/runners/window_manager.d.ts.map +1 -1
  61. package/dist/runners/window_manager.js +66 -3
  62. package/dist/runners/window_manager.js.map +1 -1
  63. package/dist/tools/discover_interactions.d.ts.map +1 -1
  64. package/dist/tools/discover_interactions.js +5 -1
  65. package/dist/tools/discover_interactions.js.map +1 -1
  66. package/dist/tools/gate_check.d.ts.map +1 -1
  67. package/dist/tools/gate_check.js +16 -2
  68. package/dist/tools/gate_check.js.map +1 -1
  69. package/dist/tools/plan_change_journey.d.ts.map +1 -1
  70. package/dist/tools/plan_change_journey.js +15 -2
  71. package/dist/tools/plan_change_journey.js.map +1 -1
  72. package/dist/tools/plan_user_journey.d.ts.map +1 -1
  73. package/dist/tools/plan_user_journey.js +5 -2
  74. package/dist/tools/plan_user_journey.js.map +1 -1
  75. package/dist/tools/run_journey.d.ts +64 -0
  76. package/dist/tools/run_journey.d.ts.map +1 -1
  77. package/dist/tools/run_journey.js +135 -6
  78. package/dist/tools/run_journey.js.map +1 -1
  79. package/dist/tools/verify.d.ts.map +1 -1
  80. package/dist/tools/verify.js +55 -11
  81. package/dist/tools/verify.js.map +1 -1
  82. package/package.json +1 -1
@@ -17,6 +17,46 @@
17
17
  import { existsSync, readFileSync, writeFileSync, readdirSync, statSync } from "fs";
18
18
  import { join } from "path";
19
19
  const FILE = "interaction_evidence.json";
20
+ /**
21
+ * P5.4 — per-platform confidence breakdown from a multi-platform journey's
22
+ * evidence. Scoring (drive-completeness only — build/tests/lint gates are
23
+ * platform-agnostic and stay in the monolithic score):
24
+ * launch_failed → 0, device_required → 10;
25
+ * completed → 60 base + up to 20 for flow pass-rate (full marks when no
26
+ * label flows ran but steps drove) + 20 for screenshots.
27
+ */
28
+ export function computePlatformBreakdown(per) {
29
+ return per.map((p) => {
30
+ if (p.status !== "completed") {
31
+ const isLaunch = p.status === "launch_failed";
32
+ return {
33
+ target: p.target,
34
+ status: p.status,
35
+ score: isLaunch ? 0 : 10,
36
+ driven_steps: p.driven_steps,
37
+ screenshots: p.screenshots,
38
+ fix_hint: isLaunch
39
+ ? `${p.target}: the app did not launch — fix the build/launch blocker for this platform (see the journey's launch notes), then re-run codeloop_verify.`
40
+ : `${p.target}: no device was available — boot one (or configure e2e.android_avd / e2e.ios_device), then re-run codeloop_verify.`,
41
+ };
42
+ }
43
+ const flowsTotal = p.mobile_flows_total ?? 0;
44
+ const flowRatio = flowsTotal > 0 ? (p.mobile_flows_passed ?? 0) / flowsTotal : p.driven_steps > 0 ? 1 : 0;
45
+ const score = Math.round(60 + 20 * flowRatio + (p.screenshots > 0 ? 20 : 0));
46
+ const weak = score < 100;
47
+ return {
48
+ target: p.target,
49
+ status: p.status,
50
+ score,
51
+ driven_steps: p.driven_steps,
52
+ screenshots: p.screenshots,
53
+ flows: flowsTotal > 0 ? `${p.mobile_flows_passed ?? 0}/${flowsTotal}` : undefined,
54
+ fix_hint: weak
55
+ ? `${p.target}: drove but incompletely (${flowsTotal > 0 ? `flows ${p.mobile_flows_passed ?? 0}/${flowsTotal}` : `${p.driven_steps} step(s)`}, ${p.screenshots} screenshot(s)) — check the failed flow labels / missing screenshots for this platform.`
56
+ : undefined,
57
+ };
58
+ });
59
+ }
20
60
  /** Persist a run_journey interaction-evidence record into its run dir. */
21
61
  export function writeInteractionEvidence(runDir, ev) {
22
62
  try {
@@ -64,6 +104,26 @@ export function evaluateInteractionEvidenceGate(input) {
64
104
  const { journeyEvidence, journeyStale, hasManualInteractionLogs } = input;
65
105
  if (journeyEvidence && !journeyStale) {
66
106
  const e = journeyEvidence.evidence;
107
+ // P5.3 — multi-platform record: every configured platform must have
108
+ // completed with driven evidence. A launch_failed iOS leg must fail the
109
+ // gate even when the Android leg drove fine.
110
+ if (e.per_platform && e.per_platform.length > 0) {
111
+ const summary = e.per_platform
112
+ .map((p) => p.status === "completed"
113
+ ? `${p.target}: ${p.driven_steps} step(s), ${p.screenshots} screenshot(s)${p.mobile_engine ? ` via ${p.mobile_engine}` : ""}`
114
+ : `${p.target}: ${p.status.toUpperCase()}`)
115
+ .join("; ");
116
+ const failing = e.per_platform.filter((p) => p.status !== "completed" || (p.driven_steps === 0 && p.screenshots === 0));
117
+ if (failing.length === 0) {
118
+ return { passed: true, reason: `codeloop_run_journey drove ALL configured platforms — ${summary}.` };
119
+ }
120
+ return {
121
+ passed: false,
122
+ reason: `Multi-platform run (e2e.platforms) is INCOMPLETE — ${summary}. ` +
123
+ `Every configured platform must produce driven evidence: fix ${failing.map((p) => p.target).join(", ")} ` +
124
+ `(or remove it from e2e.platforms), then re-run codeloop_verify.`,
125
+ };
126
+ }
67
127
  const mobile = e.mobile_engine
68
128
  ? ` (mobile engine: ${e.mobile_engine}${e.mobile_flows_total != null ? `, ${e.mobile_flows_passed ?? 0}/${e.mobile_flows_total} flow(s)` : ""})`
69
129
  : "";
@@ -1 +1 @@
1
- {"version":3,"file":"interaction_evidence.js","sourceRoot":"","sources":["../../src/evidence/interaction_evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAkB5B,MAAM,IAAI,GAAG,2BAA2B,CAAC;AAEzC,0EAA0E;AAC1E,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,EAAuB;IAC9E,IAAI,CAAC;QACH,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,gBAAwB;IAExB,IAAI,IAAI,GAA8D,IAAI,CAAC;IAC3E,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAwB,CAAC;YAC7E,IAAI,CAAC,IAAI,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO;gBAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpE,CAAC;QAAC,MAAM,CAAC;YACP,qBAAqB;QACvB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAeD;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAAC,KAA2B;IACzE,MAAM,EAAE,eAAe,EAAE,YAAY,EAAE,wBAAwB,EAAE,GAAG,KAAK,CAAC;IAC1E,IAAI,eAAe,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC;QACnC,MAAM,MAAM,GAAG,CAAC,CAAC,aAAa;YAC5B,CAAC,CAAC,oBAAoB,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,kBAAkB,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,mBAAmB,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG;YAChJ,CAAC,CAAC,EAAE,CAAC;QACP,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,8BAA8B,CAAC,CAAC,YAAY,eAAe,CAAC,CAAC,MAAM,GAAG,MAAM,KAAK,CAAC,CAAC,WAAW,iBAAiB;SACxH,CAAC;IACJ,CAAC;IACD,IAAI,wBAAwB,EAAE,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,8FAA8F;SACvG,CAAC;IACJ,CAAC;IACD,IAAI,eAAe,IAAI,YAAY,EAAE,CAAC;QACpC,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,qHAAqH;SAC9H,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,2IAA2I;KACpJ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"interaction_evidence.js","sourceRoot":"","sources":["../../src/evidence/interaction_evidence.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ declare const androidSdkResolution: import("./runners/android_sdk.js").AndroidSdkResolution;
3
+ export { androidSdkResolution };
2
4
  export declare function markVerifiedNow(cwd: string): void;
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAimBA,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4QA,QAAA,MAAM,oBAAoB,yDAA6B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AA6VhC,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEjD"}
package/dist/index.js CHANGED
@@ -216,6 +216,14 @@ function autoCloseStuckModalsEnabled() {
216
216
  }
217
217
  /** Consecutive same-dialog detections that mark a file dialog as genuinely stuck. */
218
218
  const MODAL_AUTOCLOSE_THRESHOLD = 3;
219
+ // P2.1 — Android Studio installs the SDK without putting platform-tools on
220
+ // the shell PATH. Resolve ANDROID_HOME / ANDROID_SDK_ROOT / the default
221
+ // install location ONCE at startup and append the tool dirs to PATH so every
222
+ // adb/emulator call (ours and Maestro's) just works. Resolution details are
223
+ // surfaced by `codeloop doctor` and Android launch errors.
224
+ import { ensureAndroidToolsOnPath } from "./runners/android_sdk.js";
225
+ const androidSdkResolution = ensureAndroidToolsOnPath();
226
+ export { androidSdkResolution };
219
227
  const server = new McpServer({
220
228
  name: "codeloop",
221
229
  version: "0.1.14",
@@ -1857,20 +1865,72 @@ screens_captured[], screenshots[], unsupported_count, manual_followups[], direct
1857
1865
  target_type: targetTypeSchema.optional().describe("Override the auto-detected interaction target. Accepts synonyms (web→browser, android→android_emulator, ios→ios_simulator, *_desktop→desktop)."),
1858
1866
  web_url: z.string().optional().describe("URL to open for browser targets (e.g. http://localhost:3000). Defaults to e2e.web_url from config. Start your dev server first."),
1859
1867
  max_duration_seconds: z.number().int().min(10).max(600).optional().describe("Max video recording length. Default 180s."),
1860
- }, async (params) => {
1868
+ }, async (params, extra) => {
1869
+ // P5.5 (0.1.92) — stream journey progress (boot, build heartbeat lines,
1870
+ // drive, capture) the same way verify streams phases, so a cold first
1871
+ // build doesn't look like a hang. Same safety gate as verify: only when
1872
+ // the client passed a progressToken AND is safe to stream to.
1873
+ const progressToken = extra?._meta?.progressToken;
1874
+ let journeyClientName;
1875
+ try {
1876
+ journeyClientName = server.server.getClientVersion?.()?.name;
1877
+ }
1878
+ catch {
1879
+ journeyClientName = undefined;
1880
+ }
1861
1881
  const result = await withAuth(async () => {
1862
1882
  const cwd = resolveCwd(params);
1863
1883
  const { loadConfig } = await import("./config.js");
1864
1884
  const cfg = loadConfig(cwd);
1865
- const { runJourney } = await import("./tools/run_journey.js");
1866
- return runJourney({
1885
+ const { runJourneyForPlatforms } = await import("./tools/run_journey.js");
1886
+ const { progressClientDecision } = await import("./tools/verify.js");
1887
+ const progressSafe = progressClientDecision(journeyClientName, process.env.CODELOOP_PROGRESS);
1888
+ let progressCount = 0;
1889
+ const onProgress = !progressSafe || progressToken === undefined
1890
+ ? undefined
1891
+ : (u) => {
1892
+ progressCount += 1;
1893
+ void extra
1894
+ .sendNotification({
1895
+ method: "notifications/progress",
1896
+ params: {
1897
+ progressToken,
1898
+ progress: progressCount,
1899
+ message: `${u.phase}${u.detail ? ` — ${u.detail.slice(0, 120)}` : ""} (${Math.round(u.elapsedMs / 1000)}s)`,
1900
+ },
1901
+ })
1902
+ .catch(() => { });
1903
+ };
1904
+ // P5.3 — e2e.platforms drives every listed platform sequentially; an
1905
+ // explicit target_type argument still forces a single-platform run.
1906
+ return runJourneyForPlatforms({
1867
1907
  cwd,
1868
1908
  e2e: { ...cfg.e2e, web_url: params.web_url ?? cfg.e2e?.web_url },
1869
1909
  targetApp: cfg.evidence?.target_app,
1870
1910
  targetType: params.target_type,
1871
1911
  maxDurationSeconds: params.max_duration_seconds,
1912
+ onProgress,
1872
1913
  });
1873
1914
  }, { tool: "codeloop_run_journey", cwd: resolveCwd(params), input: params });
1915
+ // Single-platform runs keep the legacy flat result shape; multi-platform
1916
+ // runs return the per-platform outcome list plus a combined directive.
1917
+ const isWrapped = result && typeof result === "object" && "outcomes" in result;
1918
+ const wrapped = isWrapped ? result : null;
1919
+ if (wrapped && !wrapped.multi) {
1920
+ const single = wrapped.outcomes[0].result;
1921
+ const directive = `\n\n${single.directive}`;
1922
+ return {
1923
+ content: withInitHint([{ type: "text", text: JSON.stringify(single, null, 2) + directive }]),
1924
+ };
1925
+ }
1926
+ if (wrapped) {
1927
+ const directives = wrapped.outcomes
1928
+ .map((o) => `── ${o.platform} ──\n${o.result.directive}`)
1929
+ .join("\n\n");
1930
+ return {
1931
+ content: withInitHint([{ type: "text", text: JSON.stringify(result, null, 2) + `\n\n${directives}` }]),
1932
+ };
1933
+ }
1874
1934
  const directive = result && typeof result === "object" && "directive" in result ? `\n\n${result.directive}` : "";
1875
1935
  return {
1876
1936
  content: withInitHint([{ type: "text", text: JSON.stringify(result, null, 2) + directive }]),
@@ -2110,8 +2170,11 @@ App logs (stdout, logcat, simctl log) are automatically captured alongside the v
2110
2170
  let binaryFreshnessDetails;
2111
2171
  if (targetType === "desktop" && appName) {
2112
2172
  try {
2113
- const { checkBinaryFreshness } = await import("./evidence/binary_freshness.js");
2114
- binaryFreshnessDetails = checkBinaryFreshness({ app_name: appName, cwd });
2173
+ // 0.1.96 prefer the actually-running process binary (E2E #14: the
2174
+ // configured path pointed at a stale publish/ copy while the running
2175
+ // app was a fresh subproject Debug build → false BINARY MISMATCH).
2176
+ const { checkBinaryFreshnessAsync } = await import("./evidence/binary_freshness.js");
2177
+ binaryFreshnessDetails = await checkBinaryFreshnessAsync({ app_name: appName, cwd });
2115
2178
  if (binaryFreshnessDetails.stale) {
2116
2179
  binaryFreshnessWarning = binaryFreshnessDetails.reason;
2117
2180
  const { recordCycleIssue } = await import("./evidence/cycle_issues.js");
@@ -3063,6 +3126,18 @@ Wait 1-2 seconds between interactions so video frames capture state changes.`, {
3063
3126
  let windowOriginOffset = null;
3064
3127
  let screenshotDims = null;
3065
3128
  if (tt === "desktop") {
3129
+ // P2.2 — Wayland-only Linux sessions can't be driven by xdotool.
3130
+ // Fail fast with the remediation directive instead of letting every
3131
+ // individual action return an unexplained success: false.
3132
+ const { waylandDirective } = await import("./runners/wayland.js");
3133
+ const waylandBlock = waylandDirective();
3134
+ if (waylandBlock && action !== "wait") {
3135
+ return {
3136
+ content: [
3137
+ { type: "text", text: JSON.stringify({ success: false, action, error: waylandBlock }, null, 2) },
3138
+ ],
3139
+ };
3140
+ }
3066
3141
  const appName = params.app_name || vr.getActiveRecordingAppName();
3067
3142
  if (appName && action !== "wait") {
3068
3143
  await wm.bringAppToFront(appName);