unity-open-mcp 0.9.0 → 1.1.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.
Files changed (144) hide show
  1. package/dist/asmdef-discovery.d.ts +35 -0
  2. package/dist/asmdef-discovery.js +171 -0
  3. package/dist/asmdef-discovery.js.map +1 -0
  4. package/dist/batch-spawn.d.ts +27 -0
  5. package/dist/batch-spawn.js +218 -24
  6. package/dist/batch-spawn.js.map +1 -1
  7. package/dist/capabilities/build-capabilities.d.ts +10 -0
  8. package/dist/capabilities/build-capabilities.js +4 -0
  9. package/dist/capabilities/build-capabilities.js.map +1 -1
  10. package/dist/capabilities/capabilities-view.d.ts +48 -0
  11. package/dist/capabilities/capabilities-view.js +93 -0
  12. package/dist/capabilities/capabilities-view.js.map +1 -0
  13. package/dist/capabilities/intent-groups.js +42 -0
  14. package/dist/capabilities/intent-groups.js.map +1 -1
  15. package/dist/capabilities/rule-catalog.js +7 -1
  16. package/dist/capabilities/rule-catalog.js.map +1 -1
  17. package/dist/capabilities/tool-groups.js +37 -2
  18. package/dist/capabilities/tool-groups.js.map +1 -1
  19. package/dist/child-supervision.d.ts +34 -0
  20. package/dist/child-supervision.js +110 -0
  21. package/dist/child-supervision.js.map +1 -0
  22. package/dist/cli/cli.js +9 -0
  23. package/dist/cli/cli.js.map +1 -1
  24. package/dist/cli/commands.js +37 -4
  25. package/dist/cli/commands.js.map +1 -1
  26. package/dist/compressible-router.js +12 -1
  27. package/dist/compressible-router.js.map +1 -1
  28. package/dist/constants.d.ts +31 -1
  29. package/dist/constants.js +31 -1
  30. package/dist/constants.js.map +1 -1
  31. package/dist/dialog-dismiss.d.ts +11 -0
  32. package/dist/dialog-dismiss.js +59 -4
  33. package/dist/dialog-dismiss.js.map +1 -1
  34. package/dist/editor-wedge.d.ts +45 -0
  35. package/dist/editor-wedge.js +111 -0
  36. package/dist/editor-wedge.js.map +1 -0
  37. package/dist/event-stream.d.ts +19 -6
  38. package/dist/event-stream.js +139 -17
  39. package/dist/event-stream.js.map +1 -1
  40. package/dist/gate-error.d.ts +2 -0
  41. package/dist/gate-error.js +9 -0
  42. package/dist/gate-error.js.map +1 -1
  43. package/dist/instance-discovery.d.ts +23 -0
  44. package/dist/instance-discovery.js +47 -1
  45. package/dist/instance-discovery.js.map +1 -1
  46. package/dist/live-client.d.ts +40 -5
  47. package/dist/live-client.js +254 -36
  48. package/dist/live-client.js.map +1 -1
  49. package/dist/offline/api.js +82 -30
  50. package/dist/offline/api.js.map +1 -1
  51. package/dist/offline/index-builders.d.ts +9 -0
  52. package/dist/offline/index-builders.js +58 -8
  53. package/dist/offline/index-builders.js.map +1 -1
  54. package/dist/offline/parse.js +5 -1
  55. package/dist/offline/parse.js.map +1 -1
  56. package/dist/process-diagnostics.d.ts +101 -19
  57. package/dist/process-diagnostics.js +197 -59
  58. package/dist/process-diagnostics.js.map +1 -1
  59. package/dist/project-settings.d.ts +36 -0
  60. package/dist/project-settings.js +96 -0
  61. package/dist/project-settings.js.map +1 -0
  62. package/dist/results.d.ts +8 -0
  63. package/dist/results.js +4 -1
  64. package/dist/results.js.map +1 -1
  65. package/dist/routers.js +4 -1
  66. package/dist/routers.js.map +1 -1
  67. package/dist/running-unity.d.ts +23 -0
  68. package/dist/running-unity.js +60 -0
  69. package/dist/running-unity.js.map +1 -1
  70. package/dist/server.js +8 -2
  71. package/dist/server.js.map +1 -1
  72. package/dist/stale-assembly-cache.d.ts +40 -0
  73. package/dist/stale-assembly-cache.js +76 -0
  74. package/dist/stale-assembly-cache.js.map +1 -0
  75. package/dist/tool-hint.d.ts +36 -0
  76. package/dist/tool-hint.js +98 -0
  77. package/dist/tool-hint.js.map +1 -0
  78. package/dist/tool-router.d.ts +47 -2
  79. package/dist/tool-router.js +652 -71
  80. package/dist/tool-router.js.map +1 -1
  81. package/dist/tools/agent-capabilities.js +27 -1
  82. package/dist/tools/agent-capabilities.js.map +1 -1
  83. package/dist/tools/baseline-create.js +1 -1
  84. package/dist/tools/baseline-create.js.map +1 -1
  85. package/dist/tools/batch-execute.js +12 -1
  86. package/dist/tools/batch-execute.js.map +1 -1
  87. package/dist/tools/bridge-status.js +21 -1
  88. package/dist/tools/bridge-status.js.map +1 -1
  89. package/dist/tools/capture-inline.js +4 -3
  90. package/dist/tools/capture-inline.js.map +1 -1
  91. package/dist/tools/editor-status.js +7 -2
  92. package/dist/tools/editor-status.js.map +1 -1
  93. package/dist/tools/execute-csharp.js +36 -3
  94. package/dist/tools/execute-csharp.js.map +1 -1
  95. package/dist/tools/execute-menu.js +33 -2
  96. package/dist/tools/execute-menu.js.map +1 -1
  97. package/dist/tools/index.d.ts +1 -0
  98. package/dist/tools/index.js +44 -0
  99. package/dist/tools/index.js.map +1 -1
  100. package/dist/tools/inputsim-key.d.ts +40 -0
  101. package/dist/tools/inputsim-key.js +72 -0
  102. package/dist/tools/inputsim-key.js.map +1 -0
  103. package/dist/tools/inputsim-pointer.d.ts +40 -0
  104. package/dist/tools/inputsim-pointer.js +121 -0
  105. package/dist/tools/inputsim-pointer.js.map +1 -0
  106. package/dist/tools/inputsim-pointer3d.d.ts +40 -0
  107. package/dist/tools/inputsim-pointer3d.js +55 -0
  108. package/dist/tools/inputsim-pointer3d.js.map +1 -0
  109. package/dist/tools/inputsim-probe.d.ts +40 -0
  110. package/dist/tools/inputsim-probe.js +43 -0
  111. package/dist/tools/inputsim-probe.js.map +1 -0
  112. package/dist/tools/inputsim-step.d.ts +40 -0
  113. package/dist/tools/inputsim-step.js +50 -0
  114. package/dist/tools/inputsim-step.js.map +1 -0
  115. package/dist/tools/inputsim-touch.d.ts +40 -0
  116. package/dist/tools/inputsim-touch.js +83 -0
  117. package/dist/tools/inputsim-touch.js.map +1 -0
  118. package/dist/tools/invoke-method.js +15 -1
  119. package/dist/tools/invoke-method.js.map +1 -1
  120. package/dist/tools/memory-snapshot-capture.js +11 -5
  121. package/dist/tools/memory-snapshot-capture.js.map +1 -1
  122. package/dist/tools/pull-events.js +18 -10
  123. package/dist/tools/pull-events.js.map +1 -1
  124. package/dist/tools/read-compile-errors.js +36 -7
  125. package/dist/tools/read-compile-errors.js.map +1 -1
  126. package/dist/tools/regression-check.js +2 -1
  127. package/dist/tools/regression-check.js.map +1 -1
  128. package/dist/tools/resource-pressure.js +21 -10
  129. package/dist/tools/resource-pressure.js.map +1 -1
  130. package/dist/tools/run-tests.js +11 -2
  131. package/dist/tools/run-tests.js.map +1 -1
  132. package/dist/tools/scan-all.js +2 -2
  133. package/dist/tools/scan-all.js.map +1 -1
  134. package/dist/tools/screenshot-window.js +18 -12
  135. package/dist/tools/screenshot-window.js.map +1 -1
  136. package/dist/tools/screenshot.js +13 -6
  137. package/dist/tools/screenshot.js.map +1 -1
  138. package/dist/tools/visual-compare.d.ts +40 -0
  139. package/dist/tools/visual-compare.js +98 -0
  140. package/dist/tools/visual-compare.js.map +1 -0
  141. package/dist/unity-log.d.ts +67 -2
  142. package/dist/unity-log.js +206 -8
  143. package/dist/unity-log.js.map +1 -1
  144. package/package.json +1 -1
@@ -30,16 +30,27 @@ export const resourcePressure = makeTool("unity_open_mcp_resource_pressure", "Sa
30
30
  "reachable — the bridge is what dies on fd-exhaustion. Resolves the live " +
31
31
  "Unity PID via the process scan (same as `bridge_status` cold-Safe-Mode " +
32
32
  "detection). Response fields: `fdCount` (null when the probe failed), " +
33
- "`fdMethod`, `approximate` (Windows handle count), `ceiling` (fixed 1024), " +
34
- "`headroom`, `pressureRatio`, `state` (`ok` | `warn` at ≥80% | `critical` " +
35
- "at ≥90% | `unknown` when the probe failed), `trend` (`stable` | `rising` " +
36
- "| `leaking` — monotonic climb across successive samples = leak in " +
37
- "progress; absolute count alone is not enough), and `samples[]` (the " +
38
- "session-scoped in-memory ring of recent samples for this PID — no disk " +
39
- "cache). When `state` is warn/critical or `trend.state` is leaking, the " +
40
- "agent should surface the risk to the operator and recommend saving scene " +
41
- "work + restarting via the Hub before the next domain reload trips the " +
42
- "ceiling. Use this after heavy automation (many recompiles / domain " +
33
+ "`fdMethod`, `approximate` (Windows handle count), `ceiling` (the resolved " +
34
+ "fd ceiling — default 1024, configurable per project), `ceilingSource` " +
35
+ "(`\"default\"` | `\"config\"` — whether `.unity-open-mcp/settings.json` " +
36
+ "`resourcePressure.fdCeiling` overrode the default), `headroom`, " +
37
+ "`pressureRatio`, `state` (`ok` | `warn` at ≥80% | `critical` at ≥90% | " +
38
+ "`over_ceiling` when the count already exceeds the ceiling proxy | " +
39
+ "`unknown` when the probe failed), `trend` (`stable` | `rising` | " +
40
+ "`leaking` — monotonic climb across successive samples = leak in progress; " +
41
+ "absolute count alone is not enough), and `samples[]` (the session-scoped " +
42
+ "in-memory ring of recent samples for this PID — no disk cache). " +
43
+ "IMPORTANT for fd-heavy projects: an asset-heavy Editor legitimately sits " +
44
+ "OVER the ceiling proxy on a fresh healthy process (lsof/HandleCount count " +
45
+ "ALL OS fds — mmap'd assets, file watchers, FileStream handles — while only " +
46
+ "Mono-IOSelector-registered descriptors trip the hang), so `over_ceiling` " +
47
+ "is INFORMATIONAL, not an alarm: when `state` is `over_ceiling` and the " +
48
+ "trend is stable/no-history the response carries a `pressureNote` instead " +
49
+ "of a `warning`, and you should watch the TREND, not the absolute. The " +
50
+ "agent should surface a `warning` (recommend saving scene work + planning a " +
51
+ "restart) when `state` is warn/critical, OR `trend.state` is " +
52
+ "leaking/rising — do NOT call `restart_editor` yet (the Editor is still " +
53
+ "healthy). Use this after heavy automation (many recompiles / domain " +
43
54
  "reloads) to catch fd growth across reloads. No disk cache — samples live " +
44
55
  "in the session store and are cleared on MCP-server restart.", {
45
56
  properties: {
@@ -1 +1 @@
1
- {"version":3,"file":"resource-pressure.js","sourceRoot":"","sources":["../../src/tools/resource-pressure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,2EAA2E;AAC3E,eAAe;AACf,EAAE;AACF,mFAAmF;AACnF,mEAAmE;AACnE,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,oDAAoD;AACpD,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,gFAAgF;AAChF,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,SAAS;AACT,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CACtC,kCAAkC,EAClC,4EAA4E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,sEAAsE;IACtE,sEAAsE;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,uEAAuE;IACvE,4EAA4E;IAC5E,2EAA2E;IAC3E,2EAA2E;IAC3E,oEAAoE;IACpE,sEAAsE;IACtE,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,wEAAwE;IACxE,qEAAqE;IACrE,2EAA2E;IAC3E,6DAA6D,EAC/D;IACE,UAAU,EAAE;QACN,GAAG,EAAE;YACH,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,WAAW,EACT,+DAA+D;gBAC/D,mEAAmE;gBACnE,mEAAmE;gBACnE,oEAAoE;gBACpE,gBAAgB;SACnB;KACF;CACN,CACF,CAAC"}
1
+ {"version":3,"file":"resource-pressure.js","sourceRoot":"","sources":["../../src/tools/resource-pressure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,2EAA2E;AAC3E,eAAe;AACf,EAAE;AACF,mFAAmF;AACnF,mEAAmE;AACnE,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,oDAAoD;AACpD,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,gFAAgF;AAChF,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,SAAS;AACT,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CACtC,kCAAkC,EAClC,4EAA4E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,sEAAsE;IACtE,sEAAsE;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,uEAAuE;IACvE,4EAA4E;IAC5E,wEAAwE;IACxE,0EAA0E;IAC1E,kEAAkE;IAClE,yEAAyE;IACzE,oEAAoE;IACpE,mEAAmE;IACnE,4EAA4E;IAC5E,2EAA2E;IAC3E,kEAAkE;IAClE,2EAA2E;IAC3E,4EAA4E;IAC5E,6EAA6E;IAC7E,2EAA2E;IAC3E,yEAAyE;IACzE,2EAA2E;IAC3E,wEAAwE;IACxE,6EAA6E;IAC7E,8DAA8D;IAC9D,yEAAyE;IACzE,sEAAsE;IACtE,2EAA2E;IAC3E,6DAA6D,EAC/D;IACE,UAAU,EAAE;QACN,GAAG,EAAE;YACH,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,WAAW,EACT,+DAA+D;gBAC/D,mEAAmE;gBACnE,mEAAmE;gBACnE,oEAAoE;gBACpE,gBAAgB;SACnB;KACF;CACN,CACF,CAAC"}
@@ -10,7 +10,11 @@ export const runTests = makeTool("unity_senses_run_tests", "Run Unity EditMode o
10
10
  "looks like 'no results' but is a no-match filter, not a failure. " +
11
11
  "Tip: to run a single test method deterministically, invoke the test " +
12
12
  "class/method directly via unity_open_mcp_invoke_method — NUnit assertion " +
13
- "failures come back verbatim in the error.", {
13
+ "failures come back verbatim in the error. " +
14
+ "This call is terminal: it starts the run AND waits for the results file, so there is no " +
15
+ "polling step for the caller to perform — `run_id` starts a run, it does not read one. " +
16
+ "It also cannot be a nested unity_open_mcp_batch_execute step (the batch route has no " +
17
+ "results poller and is refused up-front with batch_step_requires_server_poll).", {
14
18
  properties: {
15
19
  play_mode: {
16
20
  type: "boolean",
@@ -53,7 +57,12 @@ export const runTests = makeTool("unity_senses_run_tests", "Run Unity EditMode o
53
57
  },
54
58
  run_id: {
55
59
  type: "string",
56
- description: "Optional run id. Omit to let the bridge generate a safe one (<pid>-<unixMs>). " +
60
+ description: "Optional id for the run this call STARTS. It is NOT a poll handle: re-calling " +
61
+ "run_tests with the id from a previous response does not fetch that run's status — " +
62
+ "it would start a second run under the same id, so the bridge refuses it while the " +
63
+ "first is still in flight. There is nothing to poll by hand: this call already " +
64
+ "waits out `timeout_ms` and returns the terminal result (raise it for a long " +
65
+ "suite). Omit to let the bridge generate a safe one (<pid>-<unixMs>). " +
57
66
  "Must be 1..128 chars of [A-Za-z0-9._-] only.",
58
67
  },
59
68
  },
@@ -1 +1 @@
1
- {"version":3,"file":"run-tests.js","sourceRoot":"","sources":["../../src/tools/run-tests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAC9B,wBAAwB,EACxB,sEAAsE;IACpE,qEAAqE;IACrE,oDAAoD;IACpD,wDAAwD;IACxD,sEAAsE;IACtE,sEAAsE;IACtE,yEAAyE;IACzE,yEAAyE;IACzE,mEAAmE;IACnE,sEAAsE;IACtE,2EAA2E;IAC3E,2CAA2C,EAC7C;IACE,UAAU,EAAE;QACN,SAAS,EAAE;YACT,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,iEAAiE;SAC/E;QACD,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,yHAAyH;SACvI;QACD,cAAc,EAAE;YACd,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,yCAAyC;SACvD;QACD,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,6EAA6E;gBAC7E,yEAAyE;gBACzE,6BAA6B;SAChC;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,2DAA2D;SACzE;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,WAAW,EACT,kEAAkE;gBAClE,kEAAkE;gBAClE,2DAA2D;SAC9D;QACD,UAAU,EAAE;YACV,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,MAAM;YACf,WAAW,EACT,mFAAmF;gBACnF,6EAA6E;gBAC7E,uEAAuE;SAC1E;QACD,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,gFAAgF;gBAChF,8CAA8C;SACjD;KACF;CACN,CACF,CAAC"}
1
+ {"version":3,"file":"run-tests.js","sourceRoot":"","sources":["../../src/tools/run-tests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAC9B,wBAAwB,EACxB,sEAAsE;IACpE,qEAAqE;IACrE,oDAAoD;IACpD,wDAAwD;IACxD,sEAAsE;IACtE,sEAAsE;IACtE,yEAAyE;IACzE,yEAAyE;IACzE,mEAAmE;IACnE,sEAAsE;IACtE,2EAA2E;IAC3E,4CAA4C;IAC5C,0FAA0F;IAC1F,wFAAwF;IACxF,uFAAuF;IACvF,+EAA+E,EACjF;IACE,UAAU,EAAE;QACN,SAAS,EAAE;YACT,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,iEAAiE;SAC/E;QACD,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,yHAAyH;SACvI;QACD,cAAc,EAAE;YACd,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,yCAAyC;SACvD;QACD,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,6EAA6E;gBAC7E,yEAAyE;gBACzE,6BAA6B;SAChC;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,2DAA2D;SACzE;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,WAAW,EACT,kEAAkE;gBAClE,kEAAkE;gBAClE,2DAA2D;SAC9D;QACD,UAAU,EAAE;YACV,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,MAAM;YACf,WAAW,EACT,mFAAmF;gBACnF,6EAA6E;gBAC7E,uEAAuE;SAC1E;QACD,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,gFAAgF;gBAChF,oFAAoF;gBACpF,oFAAoF;gBACpF,gFAAgF;gBAChF,8EAA8E;gBAC9E,uEAAuE;gBACvE,8CAA8C;SACjD;KACF;CACN,CACF,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import { makeTool } from "./schema-fragments.js";
2
- export const scanAll = makeTool("unity_open_mcp_scan_all", "Full project scan using all ported verify rules. Runs in batch mode (headless Unity) — no open Editor required. Returns severity counts, per-rule summaries, timing, and issue details. exitCode 0 = pass, 1 = issues above fail_on_severity threshold.", {
2
+ export const scanAll = makeTool("unity_open_mcp_scan_all", "Full project scan using all ported verify rules. Runs in batch mode (headless Unity) — no open Editor required. Returns severity counts, per-rule summaries, timing, and issue details. exitCode 0 = pass, 1 = issues above fail_on_severity threshold or any verify rule threw (rulesFailed lists them — the scan is incomplete, not clean).", {
3
3
  properties: {
4
4
  platform_profile: {
5
5
  enum: ["mobile", "console", "desktop"],
6
6
  default: "desktop",
7
- description: "Stored in output metadata; does not filter rules in M5.",
7
+ description: "Applied to profile-sensitive rules (shader_analysis mobile-only detections) and echoed in output metadata. Does not filter which rules run.",
8
8
  },
9
9
  fail_on_severity: {
10
10
  enum: ["error", "warn", "info", "verbose", "never"],
@@ -1 +1 @@
1
- {"version":3,"file":"scan-all.js","sourceRoot":"","sources":["../../src/tools/scan-all.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAC7B,yBAAyB,EACzB,yPAAyP,EACzP;IACE,UAAU,EAAE;QACN,gBAAgB,EAAE;YAChB,IAAI,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;YACtC,OAAO,EAAE,SAAS;YAClB,WAAW,EAAE,yDAAyD;SACvE;QACD,gBAAgB,EAAE;YAChB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;YACnD,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,0EAA0E;SACxF;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,kFAAkF;SAChG;KACF;CACN,CACF,CAAC"}
1
+ {"version":3,"file":"scan-all.js","sourceRoot":"","sources":["../../src/tools/scan-all.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAC7B,yBAAyB,EACzB,+UAA+U,EAC/U;IACE,UAAU,EAAE;QACN,gBAAgB,EAAE;YAChB,IAAI,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;YACtC,OAAO,EAAE,SAAS;YAClB,WAAW,EAAE,6IAA6I;SAC3J;QACD,gBAAgB,EAAE;YAChB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;YACnD,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,0EAA0E;SACxF;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,kFAAkF;SAChG;KACF;CACN,CACF,CAAC"}
@@ -1,19 +1,25 @@
1
1
  import { makeTool } from "./schema-fragments.js";
2
2
  // M20 Plan 1 / T20.1.2 — Editor window screenshot. Captures any EditorWindow
3
3
  // (Console, Hierarchy, Inspector, Project, Scene, Game, or a custom window).
4
- // Full-fidelity capture via the Win32 PrintWindow API is Windows-only; on
5
- // macOS/Linux a best-effort screen-rect readback is used and the response
6
- // carries platformLimited: true so the agent knows the capture may be partial
7
- // when the window is occluded. Returns the saved PNG file path.
4
+ // feedback #6 (2026-08-07): on macOS/Linux the screen-readback path reads from
5
+ // an unbound backbuffer during bridge dispatch and produces a blank frame, so
6
+ // the tool now returns a structured `not_supported` error there (use the OS
7
+ // screen-capture tool, or screenshot {view:"composed"} for the rendered Game
8
+ // view). On Windows a screen-rect readback is used and a post-capture
9
+ // solid-color check rejects blank frames with a `blank_capture` error instead
10
+ // of reporting status:ok. `resolution` reports the actual capture size.
8
11
  export const screenshotWindow = makeTool("unity_senses_screenshot_window", "Capture a Unity Editor window (Console, Hierarchy, Inspector, Project, " +
9
- "Scene, Game, or any custom EditorWindow) to a PNG file. Full-fidelity " +
10
- "capture (occlusion-proof, no focus stealing) is Windows-only via the " +
11
- "Win32 PrintWindow API; on macOS/Linux a best-effort screen-rect readback " +
12
- "is used and the response carries platformLimited: true, so the capture " +
13
- "may be partial or stale when the window is hidden behind others. Provide " +
14
- "either window_title (visible tab text, e.g. \"Console\") or window_type " +
15
- "(EditorWindow type name, e.g. \"UnityEditor.ConsoleWindow\"). Returns " +
16
- "the saved PNG file path. Requires a live Unity Editor connection.", {
12
+ "Scene, Game, or any custom EditorWindow) to a PNG file. Windows-only: on " +
13
+ "macOS/Linux returns a `not_supported` error (the editor-window backbuffer " +
14
+ "is not bound during bridge dispatch, so a blank frame would result — use " +
15
+ "the OS screen-capture tool, or screenshot {view:\"composed\"} for the " +
16
+ "rendered Game view). On Windows a screen-rect readback is used; a blank/" +
17
+ "solid-color frame is rejected with a `blank_capture` error. `resolution` " +
18
+ "reports the ACTUAL capture size (clamped to the window's on-screen rect), " +
19
+ "not the requested maximum. Provide either window_title (visible tab text, " +
20
+ "e.g. \"Console\") or window_type (EditorWindow type name, e.g. " +
21
+ "\"UnityEditor.ConsoleWindow\"). Returns the saved PNG file path. Requires " +
22
+ "a live Unity Editor connection.", {
17
23
  properties: {
18
24
  window_title: {
19
25
  type: "string",
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot-window.js","sourceRoot":"","sources":["../../src/tools/screenshot-window.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,6EAA6E;AAC7E,6EAA6E;AAC7E,0EAA0E;AAC1E,0EAA0E;AAC1E,8EAA8E;AAC9E,gEAAgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CACtC,gCAAgC,EAChC,yEAAyE;IACvE,wEAAwE;IACxE,uEAAuE;IACvE,2EAA2E;IAC3E,yEAAyE;IACzE,2EAA2E;IAC3E,0EAA0E;IAC1E,wEAAwE;IACxE,mEAAmE,EACrE;IACE,UAAU,EAAE;QACN,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,4DAA4D;gBAC5D,mEAAmE;gBACnE,iEAAiE;gBACjE,+CAA+C;SAClD;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,0DAA0D;gBAC1D,6DAA6D;gBAC7D,mDAAmD;SACtD;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,oEAAoE;gBACpE,+BAA+B;SAClC;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,qEAAqE;gBACrE,gCAAgC;SACnC;KACF;CACN,CACF,CAAC"}
1
+ {"version":3,"file":"screenshot-window.js","sourceRoot":"","sources":["../../src/tools/screenshot-window.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,sEAAsE;AACtE,8EAA8E;AAC9E,wEAAwE;AACxE,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CACtC,gCAAgC,EAChC,yEAAyE;IACvE,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,iEAAiE;IACjE,4EAA4E;IAC5E,iCAAiC,EACnC;IACE,UAAU,EAAE;QACN,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,4DAA4D;gBAC5D,mEAAmE;gBACnE,iEAAiE;gBACjE,+CAA+C;SAClD;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,0DAA0D;gBAC1D,6DAA6D;gBAC7D,mDAAmD;SACtD;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,oEAAoE;gBACpE,+BAA+B;SAClC;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,qEAAqE;gBACrE,gCAAgC;SACnC;KACF;CACN,CACF,CAAC"}
@@ -1,16 +1,23 @@
1
1
  import { makeTool } from "./schema-fragments.js";
2
- export const screenshot = makeTool("unity_senses_screenshot", "Capture a screenshot from the Unity Editor. Supports three views: " +
3
- "'scene' (the Scene view), 'game' (the main camera / Game view), and " +
2
+ export const screenshot = makeTool("unity_senses_screenshot", "Capture a screenshot from the Unity Editor. Supports four views: " +
3
+ "'scene' (the Scene view), 'game' (renders Camera.main only — NOT the full " +
4
+ "Game view; Screen-Space Overlay UI and multi-camera compositions are NOT " +
5
+ "included), 'composed' (the player's full composite frame — every camera by " +
6
+ "depth plus Screen-Space Overlay canvases; use this to verify UI edits), and " +
4
7
  "'isolated' (a clean 2x2 composite — Front/Right/Back/Top — of a single " +
5
8
  "GameObject with layer culling and background choice). " +
6
9
  "Returns the saved PNG file path. Requires a live Unity Editor connection.", {
7
10
  properties: {
8
11
  view: {
9
12
  type: "string",
10
- enum: ["scene", "game", "isolated"],
13
+ enum: ["scene", "game", "composed", "isolated"],
11
14
  default: "scene",
12
- description: "Capture target. 'scene' = Scene view camera, 'game' = main game camera, " +
13
- "'isolated' = clean 2x2 composite of one GameObject.",
15
+ description: "Capture target. 'scene' = Scene view camera, 'game' = Camera.main only " +
16
+ "(Overlay canvases and other cameras are NOT rendered — prefer 'composed' " +
17
+ "to verify UI), 'composed' = the player's full frame (all cameras by depth + " +
18
+ "Screen-Space Overlay UI; in play mode uses ScreenCapture, in edit mode " +
19
+ "composites enabled cameras by depth), 'isolated' = clean 2x2 composite of " +
20
+ "one GameObject.",
14
21
  },
15
22
  width: {
16
23
  type: "integer",
@@ -35,7 +42,7 @@ export const screenshot = makeTool("unity_senses_screenshot", "Capture a screens
35
42
  type: "string",
36
43
  enum: ["transparent", "solid", "skybox"],
37
44
  default: "skybox",
38
- description: "Background for 'isolated' view. Ignored for scene/game.",
45
+ description: "Background for 'isolated' view. Ignored for scene/game/composed.",
39
46
  },
40
47
  },
41
48
  });
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAChC,yBAAyB,EACzB,oEAAoE;IAClE,sEAAsE;IACtE,yEAAyE;IACzE,wDAAwD;IACxD,2EAA2E,EAC7E;IACE,UAAU,EAAE;QACN,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC;YACnC,OAAO,EAAE,OAAO;YAChB,WAAW,EACT,0EAA0E;gBAC1E,qDAAqD;SACxD;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,mFAAmF;SACtF;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,oFAAoF;SACvF;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,wEAAwE;gBACxE,0CAA0C;SAC7C;QACD,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,CAAC;YACxC,OAAO,EAAE,QAAQ;YACjB,WAAW,EAAE,yDAAyD;SACvE;KACF;CACN,CACF,CAAC"}
1
+ {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAChC,yBAAyB,EACzB,mEAAmE;IACjE,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,wDAAwD;IACxD,2EAA2E,EAC7E;IACE,UAAU,EAAE;QACN,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC;YAC/C,OAAO,EAAE,OAAO;YAChB,WAAW,EACT,yEAAyE;gBACzE,2EAA2E;gBAC3E,8EAA8E;gBAC9E,yEAAyE;gBACzE,4EAA4E;gBAC5E,iBAAiB;SACpB;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,mFAAmF;SACtF;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,oFAAoF;SACvF;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,wEAAwE;gBACxE,0CAA0C;SAC7C;QACD,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,CAAC;YACxC,OAAO,EAAE,QAAQ;YACjB,WAAW,EAAE,kEAAkE;SAChF;KACF;CACN,CACF,CAAC"}
@@ -0,0 +1,40 @@
1
+ export declare const visualCompare: {
2
+ inputSchema: {
3
+ [x: string]: unknown;
4
+ type: "object";
5
+ properties?: {
6
+ [x: string]: object;
7
+ } | undefined;
8
+ required?: string[] | undefined;
9
+ };
10
+ name: string;
11
+ description?: string | undefined;
12
+ outputSchema?: {
13
+ [x: string]: unknown;
14
+ type: "object";
15
+ properties?: {
16
+ [x: string]: object;
17
+ } | undefined;
18
+ required?: string[] | undefined;
19
+ } | undefined;
20
+ annotations?: {
21
+ title?: string | undefined;
22
+ readOnlyHint?: boolean | undefined;
23
+ destructiveHint?: boolean | undefined;
24
+ idempotentHint?: boolean | undefined;
25
+ openWorldHint?: boolean | undefined;
26
+ } | undefined;
27
+ execution?: {
28
+ taskSupport?: "optional" | "required" | "forbidden" | undefined;
29
+ } | undefined;
30
+ _meta?: {
31
+ [x: string]: unknown;
32
+ } | undefined;
33
+ icons?: {
34
+ src: string;
35
+ mimeType?: string | undefined;
36
+ sizes?: string[] | undefined;
37
+ theme?: "light" | "dark" | undefined;
38
+ }[] | undefined;
39
+ title?: string | undefined;
40
+ };
@@ -0,0 +1,98 @@
1
+ import { makeTool } from "./schema-fragments.js";
2
+ // Visual regression compare — the one transferable idea worth taking from
3
+ // unity-biome-mcp's "visual baseline/diff" feature. Capture a named reference
4
+ // snapshot from a view (scene / game / isolated), then compare later captures
5
+ // against it. The bridge returns pixelDiffPercent / mismatchedPixels /
6
+ // perceptualDistance (8x8 aHash Hamming distance) / match, plus an inline diff
7
+ // image (mismatched pixels in red over the current frame) when the diff is
8
+ // non-zero. The diff image is carried as an `inlineImage` field the MCP server
9
+ // unwraps into an MCP image content block (same mechanism as capture_inline).
10
+ //
11
+ // "reference snapshot" / "visual compare" is used instead of "baseline" — that
12
+ // name is already taken by the verify-issue baseline tools (baseline_create,
13
+ // regression_check), which compare compiler-error / project-health snapshots,
14
+ // not images.
15
+ export const visualCompare = makeTool("unity_senses_visual_compare", "Visual regression compare. Capture a named reference snapshot from a view " +
16
+ "(scene / game / isolated), then compare later captures against it to check " +
17
+ "whether an edit visually broke anything. Returns pixelDiffPercent, " +
18
+ "mismatchedPixels, perceptualDistance (8x8 average-hash Hamming distance — " +
19
+ "tolerates minor anti-aliasing drift), and match (true when pixelDiffPercent " +
20
+ "<= sensitivity * 100). On a non-zero diff, returns an inline diff image " +
21
+ "(mismatched pixels highlighted red over the current frame) as an MCP image " +
22
+ "content block. Actions: 'save' (capture + store a named reference), " +
23
+ "'compare' (capture + diff vs the named reference), 'list' (enumerate saved " +
24
+ "references), 'delete' (remove a reference). References persist under " +
25
+ "~/.unity-open-mcp/screenshots/references/. Requires a live Unity Editor " +
26
+ "connection.", {
27
+ properties: {
28
+ action: {
29
+ type: "string",
30
+ enum: ["save", "compare", "list", "delete"],
31
+ description: "save: capture + store a named reference. compare: capture + diff vs " +
32
+ "the named reference. list: enumerate saved references. delete: remove " +
33
+ "a named reference.",
34
+ },
35
+ name: {
36
+ type: "string",
37
+ description: "Reference name (required for save / compare / delete). Flat filename " +
38
+ "only — no path separators or traversal. Stored as " +
39
+ "<name>.png + <name>.meta.json.",
40
+ },
41
+ view: {
42
+ type: "string",
43
+ enum: ["scene", "game", "isolated"],
44
+ default: "game",
45
+ description: "Capture target. 'scene' = Scene view camera, 'game' = main game " +
46
+ "camera (default — visual regression usually targets what the player " +
47
+ "sees), 'isolated' = clean 2x2 composite of one GameObject. Ignored " +
48
+ "for list / delete.",
49
+ },
50
+ width: {
51
+ type: "integer",
52
+ default: 1280,
53
+ minimum: 64,
54
+ maximum: 4096,
55
+ description: "Capture width in pixels. For 'isolated', this is per-quadrant. The " +
56
+ "compare resamples the current capture to the reference dimensions if " +
57
+ "they differ, so the diff is resolution-stable.",
58
+ },
59
+ height: {
60
+ type: "integer",
61
+ default: 720,
62
+ minimum: 64,
63
+ maximum: 4096,
64
+ description: "Capture height in pixels. For 'isolated', this is per-quadrant.",
65
+ },
66
+ object_path: {
67
+ type: "string",
68
+ description: "Required for 'isolated' view. Hierarchy path of the target " +
69
+ "GameObject (e.g. \"Player\" or \"Enemies/Goblin\").",
70
+ },
71
+ background: {
72
+ type: "string",
73
+ enum: ["transparent", "solid", "skybox"],
74
+ default: "skybox",
75
+ description: "Background for 'isolated' view. Ignored for scene/game.",
76
+ },
77
+ sensitivity: {
78
+ type: "number",
79
+ default: 0.01,
80
+ minimum: 0,
81
+ maximum: 1,
82
+ description: "[compare] Match threshold as a fraction of mismatched pixels (0–1). " +
83
+ "match is true when pixelDiffPercent <= sensitivity * 100. Default 0.01 " +
84
+ "= 1% pixel diff. Raise for noisier scenes (dynamic backgrounds, " +
85
+ "particle systems); 0 = require an exact match.",
86
+ },
87
+ include_diff_image: {
88
+ type: "boolean",
89
+ default: true,
90
+ description: "[compare] When true (default) and the diff is non-zero, return the " +
91
+ "diff image (current frame with mismatched pixels set to red) as an " +
92
+ "inline MCP image content block. Set false to skip the image and " +
93
+ "receive metrics only.",
94
+ },
95
+ },
96
+ required: ["action"],
97
+ });
98
+ //# sourceMappingURL=visual-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-compare.js","sourceRoot":"","sources":["../../src/tools/visual-compare.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,uEAAuE;AACvE,+EAA+E;AAC/E,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,cAAc;AACd,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CACnC,6BAA6B,EAC7B,4EAA4E;IAC1E,6EAA6E;IAC7E,qEAAqE;IACrE,4EAA4E;IAC5E,8EAA8E;IAC9E,0EAA0E;IAC1E,6EAA6E;IAC7E,sEAAsE;IACtE,6EAA6E;IAC7E,uEAAuE;IACvE,0EAA0E;IAC1E,aAAa,EACf;IACE,UAAU,EAAE;QACV,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC;YAC3C,WAAW,EACT,sEAAsE;gBACtE,wEAAwE;gBACxE,oBAAoB;SACvB;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,uEAAuE;gBACvE,oDAAoD;gBACpD,gCAAgC;SACnC;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC;YACnC,OAAO,EAAE,MAAM;YACf,WAAW,EACT,kEAAkE;gBAClE,sEAAsE;gBACtE,qEAAqE;gBACrE,oBAAoB;SACvB;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,qEAAqE;gBACrE,uEAAuE;gBACvE,gDAAgD;SACnD;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,iEAAiE;SACpE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,6DAA6D;gBAC7D,qDAAqD;SACxD;QACD,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,CAAC;YACxC,OAAO,EAAE,QAAQ;YACjB,WAAW,EAAE,yDAAyD;SACvE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;YACV,WAAW,EACT,sEAAsE;gBACtE,yEAAyE;gBACzE,kEAAkE;gBAClE,gDAAgD;SACnD;QACD,kBAAkB,EAAE;YAClB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,WAAW,EACT,qEAAqE;gBACrE,qEAAqE;gBACrE,kEAAkE;gBAClE,uBAAuB;SAC1B;KACF;IACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;CACrB,CACF,CAAC"}
@@ -43,7 +43,7 @@ export declare function projectEditorPrevLogPath(projectPath: string | null | un
43
43
  * fell back to Editor-prev.log"). */
44
44
  export interface ResolvedEditorLog {
45
45
  path: string;
46
- reason: "project_log" | "global_log" | "prev_log_live_editor" | "prev_log_fallback";
46
+ reason: "project_log" | "global_log" | "global_log_fresher" | "prev_log_live_editor" | "prev_log_fallback";
47
47
  }
48
48
  /**
49
49
  * Pick the authoritative Editor.log to read for compile-error extraction.
@@ -70,7 +70,7 @@ export interface ResolvedEditorLog {
70
70
  * rotation. `livePid` is optional; when absent the prev.log fallback only
71
71
  * triggers on a frozen-looking log, which is conservative.
72
72
  */
73
- export declare function resolveEditorLogPath(projectPath: string | null | undefined, platform?: UnityLogPlatform, livePid?: number): ResolvedEditorLog;
73
+ export declare function resolveEditorLogPath(projectPath: string | null | undefined, platform?: UnityLogPlatform, livePid?: number, globalLogPathOverride?: string): ResolvedEditorLog;
74
74
  /** Default tail size. Bounded so a multi-MB log can't blow up the tool
75
75
  * response; 256KB is ample for a compile-error burst (Unity writes the
76
76
  * diagnostics in a contiguous block near the end of the log). */
@@ -149,3 +149,68 @@ export interface StaleAssemblyResult {
149
149
  * Never throws; returns a clean "not stale" on any resolution failure.
150
150
  */
151
151
  export declare function detectStaleAssembly(projectRoot: string | null | undefined): StaleAssemblyResult;
152
+ export interface ErrorsPredateEditsResult {
153
+ /** Cited source files (project-relative) newer than the newest built DLL. */
154
+ files: string[];
155
+ /** Newest `Library/ScriptAssemblies/*.dll` mtime in epoch ms. */
156
+ dllMtimeMs: number;
157
+ }
158
+ /**
159
+ * Decide whether the reported compiler errors predate the on-disk edits to the
160
+ * files they cite.
161
+ *
162
+ * Returns `null` when the question cannot be answered (no project root, no
163
+ * built DLL mtime, no cited file resolvable inside the project) or when every
164
+ * cited file is older than the newest built assembly — i.e. a compile has run
165
+ * since the edits and the errors are current. Never throws.
166
+ */
167
+ export declare function detectErrorsPredatingEdits(citedFiles: ReadonlyArray<string>, projectRoot: string | null | undefined, dllMtimeMs: number | undefined): ErrorsPredateEditsResult | null;
168
+ export interface LogAuthorship {
169
+ /** Unity version parsed from the log header's "Unity Editor version:" line,
170
+ * e.g. "6000.5.5f1". null when the header was not present in the tail. */
171
+ logUnityVersion: string | null;
172
+ /** True when the header's "Batch mode:" line is "YES". null when absent. */
173
+ logBatchMode: boolean | null;
174
+ /** ISO timestamp parsed from the header's "Date:" line, when present. */
175
+ logDate: string | null;
176
+ }
177
+ /**
178
+ * Parse the Unity Editor.log header fields that identify WHO wrote the log.
179
+ * Scans only the tail content already read by the tool (no extra disk I/O).
180
+ *
181
+ * Returns nulls (not throws) when the header lines are absent — a long-running
182
+ * live editor's tail starts mid-log and won't contain the header, which is the
183
+ * benign case (no version to compare against, so no false mismatch).
184
+ */
185
+ export declare function parseLogAuthorship(tail: string): LogAuthorship;
186
+ export interface LogAuthorshipMismatch {
187
+ /** True when the log's Unity version differs from the live bridge's. */
188
+ versionMismatch: boolean;
189
+ /** The version that wrote the log (from the header). */
190
+ logUnityVersion: string | null;
191
+ /** The live bridge's version, when known. */
192
+ liveUnityVersion: string | null;
193
+ /** True when the log was written by a -batchmode run (not the live editor). */
194
+ logBatchMode: boolean | null;
195
+ /** One-line agent-facing warning. Empty when not a mismatch. */
196
+ hint: string;
197
+ }
198
+ /**
199
+ * Compare the log's authorship against the live bridge's Unity version. This is
200
+ * the cross-check feedback-04-08-opus §2 asks for: a batch run of a NEWER Unity
201
+ * leaves a log whose errors (e.g. a deprecation that is only an error on that
202
+ * version) cannot occur in the live editor, so surfacing them as "current"
203
+ * sends the agent chasing ghosts (or refusing to continue) for minutes.
204
+ *
205
+ * Two cheap signals, both from data already at hand:
206
+ * - the log's "Unity Editor version:" vs the live bridge unityVersion
207
+ * - the log's "Batch mode:" flag (a batch run is never the live editor)
208
+ *
209
+ * Conservative: only flags a mismatch when BOTH the log version parsed AND a
210
+ * live version is known, AND they differ. A null log version (header scrolled
211
+ * past the tail) never fires — there is nothing to compare. When the log is a
212
+ * batch run but the versions agree, we surface the batch-mode flag WITHOUT
213
+ * calling it a mismatch (the agent still benefits from knowing it is a batch
214
+ * log). The router decides how to fold this into the response.
215
+ */
216
+ export declare function compareLogAuthorship(authorship: LogAuthorship, liveUnityVersion: string | null | undefined): LogAuthorshipMismatch;