reverseport 1.5.0 → 1.7.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 (141) hide show
  1. package/README.md +71 -26
  2. package/THIRD_PARTY_NOTICES.md +1 -0
  3. package/bin/reverseport.mjs +13 -1
  4. package/dist/browser/CdpScreenshot.js +133 -5
  5. package/dist/cli/browserAdvancedCommands.js +6 -1
  6. package/dist/cli-runtime/{AnalysisProvider-CeyX2u-b.js → AnalysisProvider-BOjhIeCw.js} +1 -1
  7. package/dist/cli-runtime/{AnalysisSnapshotFiles-BuK_ymw5.js → AnalysisSnapshotFiles-CpXtlUrr.js} +3 -3
  8. package/dist/cli-runtime/{BinaryTargetResolver-CKRfFhLj.js → BinaryTargetResolver-uNu5jLfD.js} +4 -4
  9. package/dist/cli-runtime/{ClientConfigurationDocument-D0ZqgTCv.js → ClientConfigurationDocument-BvmXMdrN.js} +2 -2
  10. package/dist/cli-runtime/{ClientRegistrationStatus-DGpwJ4ry.js → ClientRegistrationStatus-BiBrkFVM.js} +3 -3
  11. package/dist/cli-runtime/{DirectAnalysis-DW3MvxW0.js → DirectAnalysis-DeVU6XXl.js} +8 -8
  12. package/dist/cli-runtime/{Doctor-CzwYS9nB.js → Doctor-DusrhiVR.js} +6 -6
  13. package/dist/cli-runtime/{ElectronFileScope-C1hUEp36.js → ElectronFileScope-k7Al_zxF.js} +1 -1
  14. package/dist/cli-runtime/{IdaConfiguration-rEjpuRQ1.js → IdaConfiguration-QsToVI_I.js} +4 -4
  15. package/dist/cli-runtime/{InventoryProjectionEvidence-Dt4Og45O.js → InventoryProjectionEvidence-bVXXybtM.js} +2 -2
  16. package/dist/cli-runtime/{InvestigationProviders-D-QCy-4c.js → InvestigationProviders-DhwicuUg.js} +1 -1
  17. package/dist/cli-runtime/{JavaScriptApplicationEvidenceGraph-CODAjVru.js → JavaScriptApplicationEvidenceGraph-CORocMEb.js} +5 -5
  18. package/dist/cli-runtime/{JavaScriptApplicationWorkflowEvidence-CCtwSg8r.js → JavaScriptApplicationWorkflowEvidence-9-Z4VWm1.js} +2 -2
  19. package/dist/cli-runtime/{JsonFiles-Ce_O5NcH.js → JsonFiles-v2nnQzBz.js} +1 -1
  20. package/dist/cli-runtime/{ManagedSnapshot-DthWfmy9.js → ManagedSnapshot-C0cIFxKC.js} +3 -3
  21. package/dist/cli-runtime/{OwnedCommand-CnK8-h3N.js → OwnedCommand-B0mAqpOm.js} +2 -2
  22. package/dist/cli-runtime/{PrivateRuntimeRoot-KNg6qLwo.js → PrivateRuntimeRoot-DMpVdoz-.js} +1 -1
  23. package/dist/cli-runtime/{ProcessOwnership-AOJaszxt.js → ProcessOwnership-Ddlg82OS.js} +1 -1
  24. package/dist/cli-runtime/{SafeOutputTree-D8z2Zrnu.js → SafeOutputTree-BYXf6HYg.js} +1 -1
  25. package/dist/cli-runtime/{SetupHost-CzzRF89z.js → SetupHost-BC1WGGjw.js} +5 -5
  26. package/dist/cli-runtime/{SupportedClients-BrZ2qZVg.js → SupportedClients-Cag4oXyu.js} +1 -1
  27. package/dist/cli-runtime/{Update-DF55X_N2.js → Update-DYBlczEy.js} +1 -1
  28. package/dist/cli-runtime/{WindowsBatchCommand-5gT-d7O4.js → WindowsBatchCommand-Chfe9gzr.js} +1 -1
  29. package/dist/cli-runtime/{ZipArtifactReader-Db65WuM_.js → ZipArtifactReader-DziTscTm.js} +1 -1
  30. package/dist/cli-runtime/{application__DirectAnalysisStatus-OZFIFjZr.js → application__DirectAnalysisStatus-CKDY-9pN.js} +2 -2
  31. package/dist/cli-runtime/{application__EnhancedTools-C__HAdqG.js → application__EnhancedTools-BRAWz8_S.js} +3 -3
  32. package/dist/cli-runtime/{application__FunctionAnalysisEvidence-fWSgvV74.js → application__FunctionAnalysisEvidence-DWYRXeqm.js} +2 -2
  33. package/dist/cli-runtime/{application__ReconstructionCoverageService-DlNt-4TY.js → application__ReconstructionCoverageService-BD8T9JLy.js} +2 -2
  34. package/dist/cli-runtime/{application__ReconstructionObligationLedgerService-CEpbUv-7.js → application__ReconstructionObligationLedgerService-DORXlBCK.js} +4 -4
  35. package/dist/cli-runtime/{application__Setup-BExVGpqG.js → application__Setup-DAqu2s8O.js} +4 -4
  36. package/dist/cli-runtime/{application__Uninstall-BVgWDCPN.js → application__Uninstall-CEp-pG4Y.js} +3 -3
  37. package/dist/cli-runtime/{application__UpdateRuntime-Dj6UIhHQ.js → application__UpdateRuntime-BFjLzGV0.js} +5 -5
  38. package/dist/cli-runtime/{application__android__AndroidApplicationService-CyynwW6Z.js → application__android__AndroidApplicationService-B_3ijho2.js} +3 -3
  39. package/dist/cli-runtime/{application__apple__AppleApplicationService-BNPcWeL8.js → application__apple__AppleApplicationService-D5tIo-c3.js} +3 -3
  40. package/dist/cli-runtime/{application__harmony__HarmonyApplicationService-W66PwMvx.js → application__harmony__HarmonyApplicationService-CRA3tGvH.js} +3 -3
  41. package/dist/cli-runtime/{application__javascript__ElectronActiveObservationService-D8VbeCxz.js → application__javascript__ElectronActiveObservationService--W_nJQk_.js} +1 -1
  42. package/dist/cli-runtime/{application__javascript__ElectronObservationService-FmXFG4f2.js → application__javascript__ElectronObservationService-tfAD3Ice.js} +1 -1
  43. package/dist/cli-runtime/{application__javascript__JavaScriptApplicationService-D-dVrmAY.js → application__javascript__JavaScriptApplicationService-CEZLGA_3.js} +11 -11
  44. package/dist/cli-runtime/{application__javascript__JavaScriptApplicationWorkflowService-Cb0jmh8J.js → application__javascript__JavaScriptApplicationWorkflowService-D3TC2eRI.js} +5 -5
  45. package/dist/cli-runtime/{application__javascript__JavaScriptRuntimeReconciliationService-D55gO7Gq.js → application__javascript__JavaScriptRuntimeReconciliationService-CBhOf3VW.js} +4 -4
  46. package/dist/cli-runtime/{application__javascript__JavaScriptSemanticTraceService-DivM-Ym-.js → application__javascript__JavaScriptSemanticTraceService-BcLmz5aS.js} +4 -4
  47. package/dist/cli-runtime/{artifacts__ArtifactProvider-B_4h3RAw.js → artifacts__ArtifactProvider-Vi0e4diS.js} +10 -10
  48. package/dist/cli-runtime/{binary-9Gt3vJ1P.js → binary-BS-WxQAw.js} +20 -20
  49. package/dist/cli-runtime/{browserScenario-CTNr5ISp.js → browserScenario-CkFQ5Rmd.js} +3 -3
  50. package/dist/cli-runtime/{catalogIdentity-EYVhBUYJ.js → catalogIdentity-D843Oy_i.js} +2 -2
  51. package/dist/cli-runtime/cli.js +177 -63
  52. package/dist/cli-runtime/{composition__browserScenario-DNr3A_BM.js → composition__browserScenario-Ct2YyVW4.js} +1 -1
  53. package/dist/cli-runtime/{composition__electronObservation-DNw1f38M.js → composition__electronObservation-DoZILMUH.js} +2 -2
  54. package/dist/cli-runtime/{composition__electronScenario-Cu7PX270.js → composition__electronScenario-DBBedpL1.js} +2 -2
  55. package/dist/cli-runtime/{doctorRuntime-D5y43lEp.js → doctorRuntime-c5GxpwJd.js} +3 -3
  56. package/dist/cli-runtime/{dosMz-pwwUuxyC.js → dosMz-BZKOsUf9.js} +1 -1
  57. package/dist/cli-runtime/{dotnet__ManagedStaticProvider-BSnWggeb.js → dotnet__ManagedStaticProvider-DiSbEgZQ.js} +1 -1
  58. package/dist/cli-runtime/{enhancedInputs-K8C_o3b4.js → enhancedInputs-ItbV9oua.js} +1 -1
  59. package/dist/cli-runtime/{javascriptApplicationGraph-DUWeec4O.js → javascriptApplicationGraph-DaHZ_j74.js} +1 -1
  60. package/dist/cli-runtime/{javascriptExportReturnShapeProjection-BVbnAdOd.js → javascriptExportReturnShapeProjection-5R4b1b65.js} +2 -2
  61. package/dist/cli-runtime/{javascriptExportShapeComparisonSchemas-BzSil7ft.js → javascriptExportShapeComparisonSchemas-CabiAG0g.js} +2 -2
  62. package/dist/cli-runtime/{javascriptRuntimeObservation-9xTNoKY2.js → javascriptRuntimeObservation-Kk7etMNj.js} +2 -2
  63. package/dist/cli-runtime/{javascriptRuntimeReconciliation-CneBtMvx.js → javascriptRuntimeReconciliation-DuZmwI3R.js} +4 -4
  64. package/dist/cli-runtime/{javascriptRuntimeReconciliationSchemas-D1Mrb_Y0.js → javascriptRuntimeReconciliationSchemas-BoiwFBmk.js} +3 -3
  65. package/dist/cli-runtime/{javascriptSemanticTraceSchemas-BHItrqIA.js → javascriptSemanticTraceSchemas-BlqTEtah.js} +2 -2
  66. package/dist/cli-runtime/{lipo-BCA3wVyN.js → lipo-BA5qA_xF.js} +3 -3
  67. package/dist/cli-runtime/{managedApplicationGraph-BqOr01E6.js → managedApplicationGraph-bNZH8_q9.js} +2 -2
  68. package/dist/cli-runtime/{managedToolContracts-BSy4TRaK.js → managedToolContracts-_YDzyE2p.js} +2 -2
  69. package/dist/cli-runtime/mcpDoctor.js +3 -3
  70. package/dist/cli-runtime/{native__NativeMacOSProvider-BIG9iCcj.js → native__NativeMacOSProvider-C5fgPPf0.js} +10 -10
  71. package/dist/cli-runtime/{reconstructionObligationLedgerSchemas-dvp6PEnZ.js → reconstructionObligationLedgerSchemas-CBxjNJ5m.js} +27 -3
  72. package/dist/cli-runtime/{scanCanonical-Bi6si9nb.js → scanCanonical-Dt1Hf-XQ.js} +4 -4
  73. package/dist/cli-runtime/{snapshotEnvironment-B5Ai0mha.js → snapshotEnvironment-CF3KJGdj.js} +1 -1
  74. package/dist/cli-runtime/{toolContracts-C7pvYKxF.js → toolContracts-DrZdzzVJ.js} +20 -13
  75. package/dist/cli-runtime/{toolEffects-DW31yTSx.js → toolEffects-JovaVppR.js} +2 -2
  76. package/dist/cli-runtime/{workflowInputError-26EGiDpx.js → workflowInputError-uPF2Przv.js} +1 -1
  77. package/dist/contracts/browserToolContracts.js +9 -1
  78. package/dist/domain/webScreenshot.js +32 -0
  79. package/dist/generatedPackageMetadata.js +1 -1
  80. package/dist/mcp/{AnalysisSnapshotFiles-DbgHi36O.js → AnalysisSnapshotFiles-DRJXahG3.js} +2 -2
  81. package/dist/mcp/{ArtifactProvider-BNxKlaKX.js → ArtifactProvider-D8Sojfsy.js} +4 -4
  82. package/dist/mcp/{ArtifactProviderMetadata--hy-wyJK.js → ArtifactProviderMetadata-DDXT41IA.js} +1 -1
  83. package/dist/mcp/{BinaryTargetResolver-DbiUzRLh.js → BinaryTargetResolver-w52tdHfN.js} +2 -2
  84. package/dist/mcp/{DirectAnalysis-BWAu8Ro5.js → DirectAnalysis-CaeqptL4.js} +6 -6
  85. package/dist/mcp/{DirectAnalysisStatus-DofNPhKd.js → DirectAnalysisStatus-DTwOtxgh.js} +1 -1
  86. package/dist/mcp/{ManagedStaticProvider-CXE93Bow.js → ManagedStaticProvider-01USDXJF.js} +3 -3
  87. package/dist/mcp/{NativeMacOSProvider-BbITFLHW.js → NativeMacOSProvider-C_Mjc0mG.js} +4 -4
  88. package/dist/mcp/{NativeMacOSProviderMetadata-mxDhaNJf.js → NativeMacOSProviderMetadata-C6Ov3ewq.js} +1 -1
  89. package/dist/mcp/{artifactToolContracts-TXegBBr1.js → artifactToolContracts-h0iSzOnt.js} +1 -1
  90. package/dist/mcp/{browserObservation-BCgaDRyQ.js → browserObservation-Dxo7O6PX.js} +116 -6
  91. package/dist/mcp/{browserScenario-z7jveI9P.js → browserScenario-CFz4w9YN.js} +1 -1
  92. package/dist/mcp/{browserScenarioCapture-BvnKTmtZ.js → browserScenarioCapture-Cn6A6diD.js} +1 -1
  93. package/dist/mcp/{emptyArraySchema-DEEefG2V.js → emptyArraySchema-CJFbNjT7.js} +27 -3
  94. package/dist/mcp/{main-WQSCuTNt.js → main-DH7dl4Gx.js} +22 -22
  95. package/dist/mcp/main.js +1 -1
  96. package/dist/mcp/{managedToolContracts-o5LHFwHc.js → managedToolContracts-BVLgbsNv.js} +1 -1
  97. package/dist/mcp/{scanCanonical-2GN0h-BE.js → scanCanonical-B6OUfBVK.js} +2 -2
  98. package/dist/mcp/{serverIdentity-rOY69sxc.js → serverIdentity-CwMs2Ey4.js} +1 -1
  99. package/dist/mcp/{toolContracts-CrfYDTUz.js → toolContracts-BMgXB36_.js} +14 -7
  100. package/dist/mcp/{toolOutputSchemaGroups-ChxVLGoy.js → toolOutputSchemaGroups-CwPpULLy.js} +1 -1
  101. package/dist/mcp/{webSourceLocation-Dnkpf0R2.js → webSourceLocation-BkuEbXcI.js} +2 -2
  102. package/licenses/README.md +1 -0
  103. package/licenses/godot-engine-MIT.txt +20 -0
  104. package/native/windows/build/manifest.json +1 -1
  105. package/package.json +1 -1
  106. package/port/cli.mjs +6 -4
  107. package/port/knowledge/apis/godot-3-to-4-renames.json +1 -0
  108. package/port/knowledge/apis/godot-3.json +1 -0
  109. package/port/knowledge/apis/godot-4.3.json +1 -0
  110. package/port/knowledge/apis/godot-4.7.json +1 -0
  111. package/port/src/agent.mjs +1 -1
  112. package/port/src/agentdisk.mjs +83 -0
  113. package/port/src/apicheck.mjs +280 -0
  114. package/port/src/archive.mjs +34 -4
  115. package/port/src/convert.mjs +3 -1
  116. package/port/src/dormant.mjs +159 -0
  117. package/port/src/formats.mjs +1 -0
  118. package/port/src/gamearchives.mjs +476 -0
  119. package/port/src/godotbin.mjs +544 -0
  120. package/port/src/il2cpp.mjs +148 -0
  121. package/port/src/jsworkspace.mjs +2 -2
  122. package/port/src/knowledge.mjs +3 -1
  123. package/port/src/physics.mjs +135 -0
  124. package/port/src/plan.mjs +94 -11
  125. package/port/src/porters.mjs +87 -5
  126. package/port/src/refs.mjs +120 -0
  127. package/port/src/rpgmaker.mjs +416 -0
  128. package/port/src/save.mjs +326 -0
  129. package/port/src/scene.mjs +37 -3
  130. package/port/src/shader.mjs +385 -0
  131. package/port/src/strings.mjs +327 -0
  132. package/port/src/tools.mjs +48 -8
  133. package/port/src/trace.mjs +302 -0
  134. package/port/src/unity-anim.mjs +229 -0
  135. package/port/src/upgrade.mjs +219 -0
  136. package/skills/build-inspector/SKILL.md +8 -0
  137. package/skills/godot-port/SKILL.md +2 -0
  138. package/skills/port-verify/SKILL.md +20 -9
  139. package/skills/reverse-engineer-anything/SKILL.md +18 -2
  140. package/skills/reverse-engineer-anything/references/porting-and-rebuilds.md +35 -4
  141. package/skills/unity-to-godot/SKILL.md +14 -2
package/README.md CHANGED
@@ -21,7 +21,7 @@ npx reverseport setup
21
21
 
22
22
  <sub>A real run on <a href="https://github.com/godotengine/godot-demo-projects/tree/master/2d/platformer">Godot's 2D platformer demo</a>, JSON trimmed to the key fields.</sub>
23
23
 
24
- [Website](https://laaielichter.github.io/Reverseport/) · [Quick start](#quick-start) · [Every agent](#works-with-every-agent) · [What it does](#what-it-does) · [How it compares](#how-it-compares) · [FAQ](#faq) · [Docs](#documentation)
24
+ [Website](https://laaielichter.github.io/Reverseport/) · [Quick start](#quick-start) · [Every agent](#works-with-every-agent) · [Skills](#skills) · [What it does](#what-it-does) · [How it compares](#how-it-compares) · [FAQ](#faq) · [Changelog](CHANGELOG.md) · [Docs](#documentation)
25
25
 
26
26
  </div>
27
27
 
@@ -34,7 +34,8 @@ unit, verified. No files at all? Give it a name or a store page.
34
34
  ReversePort gives agents one consistent way to do all of that:
35
35
 
36
36
  - 🔍 **Understand anything** — engine and version of any project or exported game, dependency graphs, scenes,
37
- symbols in 30+ languages, executables, packs and unknown data. No build step, no dependencies.
37
+ symbols in 30+ languages, executables, packs and unknown data. JS/TS monorepos (pnpm, Turborepo, Nx, Lerna, Rush,
38
+ tsconfig paths) and Rust workspaces resolve too. No build step, no dependencies.
38
39
  - 🧠 **Go deep** — decompile, cross-reference and trace native, managed (.NET), Android, Electron/JavaScript,
39
40
  WebAssembly, firmware and browser targets through Ghidra, Hopper, IDA, JADX and more. ReversePort connects to the
40
41
  tools you have installed, drives them and shows the evidence behind every conclusion.
@@ -112,23 +113,64 @@ Built for the agent's circumstances too:
112
113
  can switch itself with `set_tool_profile`.
113
114
  - **One error shape everywhere**, with a code, whether retrying helps, and the exact next step.
114
115
  - **A `next` field wherever there is an obvious next step** (graphs, truncated results, every porting step), with the exact call.
116
+ - **Big results do not flood the context.** Answers over 256 KB are saved to `~/.reverseport/tool-output/`; the
117
+ agent gets a short version with the path. Slightly wrong input from smaller models is repaired where it is safe.
115
118
  - **Agents are heard.** `share_feedback` leaves a note for the maintainers; it stays on the user's machine until
116
119
  they share it.
117
120
 
118
121
  See [Connect any agent](docs/connect-any-agent.md).
119
122
 
123
+ ## Skills
124
+
125
+ Setup and the Claude Code plugin install skills that teach the agent the workflows, so it knows which tool comes
126
+ next without being told:
127
+
128
+ | Skill | Use it for |
129
+ | ------------------ | -------------------------------------------------------------------------------------------------------- |
130
+ | `reverse-engineer` | "How does this work?" — engine and stack, architecture, dependency graph, classes, scenes, unknown files |
131
+ | `build-inspector` | Exported builds: engine and version, what is inside the `.pck` or Unity/Unreal build, what changed |
132
+ | `rebuild` | No files: find out how a game, app or site is built, then write a measured clean-room rebuild spec |
133
+ | `port-project` | Any port, unit by unit in dependency order, with API maps, converted scenes and a verified result |
134
+ | `godot-port` | Godot 4 → Unity, Unreal, three.js or Godot C#: signals, node paths, autoloads, physics, input, axes |
135
+ | `unity-to-godot` | Unity → Godot 4: MonoBehaviours, prefabs and scenes to `.tscn`, colliders, rigidbodies |
136
+ | `port-verify` | The finish line: fix leftovers and missing functions, then hand over with an honest list of what is left |
137
+ | `proof-case` | Keep an investigation honest: evidence, claims that cite it, decisions, tests and open unknowns |
138
+ | `troubleshoot` | Errors and odd results: unreadable scenes, packs that will not list, refused paths, MCP problems |
139
+
140
+ The Claude Code plugin also adds the `port-architect` agent, which runs a whole port from recon to hand-over, and
141
+ [guard hooks](docs/proof-and-memory.md) that ask before a tool attaches to a program and stop a "done" while a proof
142
+ case fails its check.
143
+
144
+ A skill copied into an agent's folder can be older than the installed tool. `reverseport skills` lists the skills of
145
+ the version you have and `reverseport skills get <name>` prints the matching guide.
146
+
120
147
  ## Prompts to try
121
148
 
122
- | You ask | ReversePort does |
123
- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
124
- | _What is this game made with, and how is it built?_ | `re_scan` → engine + version, languages, entry points, how it starts |
125
- | _Map this codebase and write ARCHITECTURE.md._ | `re_graph`, `re_symbols`, `re_report` |
126
- | _What changed between build 43 and 44?_ | `re_compare` folder-to-folder and pack-to-pack, biggest changes first |
127
- | _Decompile the function that saves settings in this app and explain it._ | opens the binary, finds it, decompiles it, shows the evidence |
128
- | _How does this Electron app talk to its native side?_ | maps modules, IPC and Electron boundaries |
129
- | _What is `<some game>` made with? I don't have the files._ | `re_lookup` from public sources: engine with confidence, stack, layout, remakes |
130
- | _Rebuild the movement of `<game>` as precisely as possible in Godot._ | `re_blueprint`: systems, parameters to measure, parity table, skeleton |
131
- | _Port my Godot game to Unity._ | `port_plan` → `port_unit`/`port_write` loop → `port_scene` → `port_verify` |
149
+ | You ask | ReversePort does |
150
+ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
151
+ | _What is this game made with, and how is it built?_ | `re_scan` → engine + version, languages, entry points, how it starts |
152
+ | _Map this codebase and write ARCHITECTURE.md._ | `re_graph`, `re_symbols`, `re_report` |
153
+ | _How do the packages in this Turborepo/pnpm monorepo depend on each other?_ | `re_scan` finds the workspace and its packages; `re_graph` resolves workspace names and tsconfig paths and shows who uses whom |
154
+ | _Show me how this button on the website is built._ | `capture_web_screenshot` with a `selector`: a cropped image of the element, its HTML and its computed CSS |
155
+ | _All I have is data.win / an .rpa / a .pak / a .swf / a sound bank / a web build._ | `re_archive`: names, assets and facts out of GameMaker, Ren'Py, Unreal, Flash, FMOD, Wwise, Unity WebGL and Emscripten containers |
156
+ | _I only have the exported Godot game, not the project._ | `re_archive` extracts the .pck, `re_decode` turns .gdc/.scn/.res/project.binary back into an editable project |
157
+ | _A Unity IL2CPP game without its C# source._ | `re_il2cpp`: classes, methods and literals from global-metadata.dat, plus a C# skeleton |
158
+ | _What changed between build 43 and 44?_ | `re_compare` folder-to-folder and pack-to-pack, biggest changes first |
159
+ | _Why are my Unity materials pink and scripts "missing" after a move?_ | `re_refs`: dangling, duplicate and missing GUIDs, with remap suggestions |
160
+ | _Get every player-facing string out of this game so we can translate it._ | `re_strings`: .pot/.csv with ids and placeholders; `apply` writes a translated copy |
161
+ | _Is this GDScript valid for Godot 4.3, or did the model mix in Godot 3?_ | `re_apicheck`: renamed names with replacements, invented members, too-new classes |
162
+ | _What is in this save file, is it checksummed, and which field is the gold?_ | `re_save`: layers, fields with roles, verified checksums, diff of two saves, schema + SaveData classes |
163
+ | _Upgrade my Godot 3 game to Godot 4._ | `port_upgrade`: converted copy (renames, @annotations, await, signals, scenes, project.godot) + what needs a human |
164
+ | _Decompile the function that saves settings in this app and explain it._ | opens the binary, finds it, decompiles it, shows the evidence |
165
+ | _How does this Electron app talk to its native side?_ | maps modules, IPC and Electron boundaries |
166
+ | _What is `<some game>` made with? I don't have the files._ | `re_lookup` from public sources: engine with confidence, stack, layout, remakes |
167
+ | _Rebuild the movement of `<game>` as precisely as possible in Godot._ | `re_blueprint`: systems, parameters to measure, parity table, skeleton |
168
+ | _Port my Unity UI, prefab variants and Animator to Godot._ | `port_scene`: Control nodes with anchors, inherited scenes, AnimationPlayer + state machine from .anim/.controller |
169
+ | _Port this Unity shader (or a Shadertoy) to Godot._ | `port_shader`: uniforms, intrinsics and built-ins mapped, `PORT:` markers and leftovers for the rest |
170
+ | _Why does my ported game fall, slide and jump differently?_ | `port_convert {physics}`: gravity, fixed step, damping, friction/bounce rules, layers → masks, jump velocity recomputed |
171
+ | _Does the port really behave the same?_ | `port_verify` flags tick/delta/seed/order differences; `port_trace` logs both per tick and finds the first divergence |
172
+ | _Move my RPG Maker MV/MZ game to Godot._ | `port_rpgmaker`: maps drawn from the tilesets, events running, database autoload, list of what is left |
173
+ | _Port my Godot game to Unity._ | `port_plan` → `port_unit`/`port_write` loop → `port_scene` → `port_verify` |
132
174
 
133
175
  ```text
134
176
  You: Port my Godot game to Unity.
@@ -151,7 +193,7 @@ Agent: re_scan → Godot 4.3, 6 scripts, 5 scenes, main scene main.tscn, autolo
151
193
  | .NET assemblies | Metadata, CIL, native boundaries, build comparisons | Nothing |
152
194
  | Android | Manifest, classes, decompiled methods, references, resources, devices | JADX / Apktool / adb ([guide](docs/android-analysis.md)) |
153
195
  | JavaScript and Electron | Modules, imports, source maps, Electron boundaries, runtime observation | Nothing; a browser for runtime |
154
- | Websites | Page, network and runtime evidence; stack fingerprint without files | A browser for runtime |
196
+ | Websites | Page, network and runtime evidence; one element by CSS selector (cropped image, HTML, computed CSS); stack fingerprint without files | A browser for runtime |
155
197
  | Firmware, EVM, crashes, captures | Regions and extraction, selectors, recorded crashes, HAR/mitmproxy captures | See the [guides](docs/index.md) |
156
198
 
157
199
  ### Rebuild and port
@@ -182,6 +224,7 @@ reverseport blueprint --lookup-id <id> # clean-room rebuild spec + par
182
224
  reverseport plan ./MyGame --to unity # start a port
183
225
  reverseport case init --question "…" --target ./Build # proof case: evidence → claims → decision → tests
184
226
  reverseport doctor # check engines and agent registrations
227
+ reverseport skills get port-project # the skill guide that matches this version
185
228
  reverseport help # overview · reverseport port help · reverseport engine --help
186
229
  ```
187
230
 
@@ -192,13 +235,14 @@ Install the command for regular use with `npm install --global reverseport`, or
192
235
 
193
236
  One MCP server (`reverseport mcp`) serves every tool:
194
237
 
195
- | ReversePort tools | |
196
- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
197
- | `re_scan` `re_graph` `re_symbols` `re_scene` | projects and builds: engine, dependencies, symbols, scenes |
198
- | `re_binary` `re_archive` `re_probe` `re_extract` `re_compare` `re_report` | executables, packs, unknown data, diffs, ARCHITECTURE.md |
199
- | `re_lookup` `re_blueprint` | recon without files, clean-room rebuild specs |
200
- | `port_map` `port_convert` `port_plan` `port_unit` `port_write` `port_scene` `port_copy_assets` `port_status` `port_verify` | porting, verified |
201
- | `re_case` | proof case: evidence, claims, unknowns, decisions, tests |
238
+ | ReversePort tools | |
239
+ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
240
+ | `re_scan` `re_graph` `re_symbols` `re_scene` | projects and builds: engine, dependencies, symbols, scenes |
241
+ | `re_binary` `re_archive` `re_probe` `re_extract` `re_compare` `re_refs` `re_strings` `re_apicheck` `re_save` `re_decode` `re_il2cpp` `re_report` | executables, packs (Godot, zip, asar, Ren'Py, GameMaker, FMOD/Wwise, Unreal, SWF), unknown data, diffs, GUID audit, localisation, API check, save files, ARCHITECTURE.md |
242
+ | `re_lookup` `re_blueprint` | recon without files, clean-room rebuild specs |
243
+ | `port_map` `port_convert` `port_plan` `port_unit` `port_write` `port_scene` `port_copy_assets` `port_status` `port_verify` | porting, verified |
244
+ | `port_upgrade` `port_shader` `port_trace` `port_rpgmaker` | Godot 3 → 4 as a converted copy plus the manual list; shader first drafts; per-tick behaviour traces compared |
245
+ | `re_case` | proof case: evidence, claims, unknowns, decisions, tests |
202
246
 
203
247
  Next to these come the deep-analysis tools — `open_binary`, `procedure_pseudo_code`, `xrefs`, `search_strings`, `analyze_javascript_application`,
204
248
  `inspect_android_package`, `inspect_managed_artifact`, `observe_web_session` and many more. `engine_tools` lists them from the running server, and
@@ -225,8 +269,9 @@ DRM, anti-cheat or licensing. See [RESPONSIBLE-USE.md](RESPONSIBLE-USE.md).
225
269
  **Does it upload my files?** No. It runs on your machine, only reads the target and writes output to new folders.
226
270
 
227
271
  **Does it port my code automatically?** Scenes, transforms and assets convert automatically. Code is written by your
228
- agent, one unit at a time, with an API map for the engine pair; `port_verify` then checks for leftovers and missing
229
- functions.
272
+ agent, one unit at a time, with an API map for the engine pair; `port_verify` then checks for leftovers, missing
273
+ functions and dormant logic (stub bodies, functions nothing calls, silenced warnings), so a port that "compiles" but
274
+ does nothing is not reported as done.
230
275
 
231
276
  **Do I need Ghidra?** Only for decompiling native binaries. Scanning, packs, lookup, blueprints and porting need
232
277
  nothing extra.
@@ -242,10 +287,10 @@ command and its JSON error. Every error names the next step, so include that lin
242
287
  Two small tools from the same author that work well next to ReversePort. Both are local, open source and have their
243
288
  own MCP server, and both install from the ReversePort marketplace:
244
289
 
245
- | Tool | What it does | Claude Code |
246
- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
247
- | [**Stashpad**](https://github.com/laaielichter/stashpad) | Memory for agents that you can read, edit and trust: plain Markdown files with a source and dates, a review queue for agent writes, and a handoff note for the next session. `re_case remember` sends a proof case's findings there ([how](docs/proof-and-memory.md#memory-across-sessions-stashpad-optional)). | `/plugin install stashpad@reverseport` |
248
- | [**agentdisk**](https://github.com/laaielichter/agentdisk) | The disk report for coding agents: the worktrees, checkpoints, `node_modules`, `.venv` and `.godot/` folders agents leave behind (porting work makes plenty), and a cleanup you can undo. Needs the `agentdisk` binary ([install](https://github.com/laaielichter/agentdisk#install)). | `/plugin install agentdisk@reverseport` |
290
+ | Tool | What it does | Claude Code |
291
+ | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
292
+ | [**Stashpad**](https://github.com/laaielichter/stashpad) | Memory for agents that you can read, edit and trust: plain Markdown files with a source and dates, a review queue for agent writes, and a handoff note for the next session. `re_case remember` sends a proof case's findings there ([how](docs/proof-and-memory.md#memory-across-sessions-stashpad-optional)). | `/plugin install stashpad@reverseport` |
293
+ | [**agentdisk**](https://github.com/laaielichter/agentdisk) | The disk report for coding agents: the worktrees, checkpoints, `node_modules`, `.venv` and `.godot/` folders agents leave behind (porting work makes plenty), and a cleanup you can undo. `reverseport port doctor` uses it to show what the workspace would really free ([how](docs/installation.md#disk-use-agentdisk-optional)). Needs the `agentdisk` binary ([install](https://github.com/laaielichter/agentdisk#install)). | `/plugin install agentdisk@reverseport` |
249
294
 
250
295
  Add the marketplace first with `/plugin marketplace add laaielichter/reverseport`. Other agents: see each project's
251
296
  README.
@@ -20,6 +20,7 @@ notices supplied with the software you actually obtain or redistribute.
20
20
  | EVM analysis | `evmole@0.9.3`, MIT, copyright 2023 Maxim Andreev. The published npm archive omits its license document; ReversePort retains the [original upstream license](third_party/evmole/LICENSE) and [provenance](third_party/evmole/README.md). It is also included in the runtime notices. |
21
21
  | Windows native addon | The release addon is compiled with MinGW-w64 and statically links GCC runtime libraries. Preserve the [MinGW-w64 runtime notices](licenses/MinGW-w64-runtime.txt), [GPLv3 text](licenses/GPL-3.0.txt), and [GCC Runtime Library Exception 3.1](licenses/GCC-Runtime-Library-Exception-3.1.txt). The exception governs eligible compiled combinations; it does not relicense the runtime itself under MIT. The Node-API build headers are from Node 22.19.0; its [original license and component notices](licenses/Node-22.19.0-LICENSE.txt) are retained. Node itself is supplied by the user. Snapshot provenance and release-toolchain review requirements are in [licenses/README.md](licenses/README.md). |
22
22
  | Proof cases | `port/src/proofcase.mjs` is a Node port of `skills/digfox/scripts/proof.py` from [Devaretanmay/digfox](https://github.com/Devaretanmay/digfox/tree/4925920), MIT, copyright 2026 Digfox contributors. The [skills/proof-case](skills/proof-case/SKILL.md) skill adapts its workflow. Preserve the [Digfox MIT notice](licenses/digfox-MIT.txt). |
23
+ | Godot API snapshots | `port/knowledge/apis/godot-*.json` are name-only snapshots (classes, members, signals, constants) derived from `extension_api-4-*.json` in [godotengine/godot-cpp](https://github.com/godotengine/godot-cpp/tree/2bb1acf) and `api.json` in [godotengine/godot-headers](https://github.com/godotengine/godot-headers/tree/9aea2a1); `godot-3-to-4-renames.json` is converted from `editor/project_upgrade/renames_map_3_to_4.cpp` in [godotengine/godot](https://github.com/godotengine/godot/tree/81ab961). All MIT, copyright Godot Engine contributors; preserve the [Godot MIT notice](licenses/godot-engine-MIT.txt). |
23
24
  | Guard hooks | `port/hooks/guard.mjs` follows the hook points of [juan-viox/rea-jev](https://github.com/juan-viox/rea-jev/tree/3104d0d), MIT, copyright 2026 Juan Alvarado, and reuses its list of runtime-class tool names. Preserve the [rea-jev MIT notice](licenses/rea-jev-MIT.txt). |
24
25
  | Challenge self-check | `bench/challenges/generate.mjs`, `large.mjs` and `oracle.mjs` are vendored unchanged (apart from a header note) from [pablodiazjorge/rea-lab](https://github.com/pablodiazjorge/rea-lab/tree/67caf0e), MIT, copyright 2026 pablodiazjorge. Preserve the [rea-lab MIT notice](licenses/rea-lab-MIT.txt). Not part of the npm package. |
25
26
  | Dinosaur website example | Selected excerpts from [wayou/t-rex-runner](https://github.com/wayou/t-rex-runner/tree/5455bfa408ec6b707c7300ff194b7390733a766d), derived from Chromium's dinosaur game. The website retains the [original BSD-3-Clause notices](website/public/assets/licenses/dinosaur.txt), including Chromium authors and wayou. This asset is not part of the npm runtime. |
@@ -17,7 +17,9 @@ const VERSION = JSON.parse(readFileSync(path.join(REPO, 'package.json'), 'utf8')
17
17
  const PORT_COMMANDS = new Set([
18
18
  'scan', 'graph', 'symbols', 'scene', 'binary', 'bin', 'archive', 'pck', 'probe', 'extract', 'carve', 'diff',
19
19
  'compare-builds', 'report', 'lookup', 'recon', 'web', 'blueprint', 'rebuild', 'map', 'convert', 'plan', 'unit',
20
- 'write', 'port-scene', 'copy-assets', 'status', 'verify', 'case', 'proof', 'tools', 'serve', 'describe', 'feedback', 'connect', 'skills',
20
+ 'write', 'port-scene', 'copy-assets', 'status', 'verify', 'case', 'proof', 'tools', 'serve', 'describe', 'feedback',
21
+ 'connect', 'skills', 'refs', 'guids', 'strings', 'i18n', 'l10n', 'apicheck', 'api', 'upgrade', 'godot3to4', 'save',
22
+ 'savefile', 'shader', 'trace', 'rpgmaker', 'rpgm', 'decode', 'gdc', 'il2cpp',
21
23
  ]);
22
24
  const ALWAYS_ENGINE = ['setup', 'doctor', 'update', 'uninstall', 'mcp', 'capabilities', 'providers', 'help'];
23
25
 
@@ -61,6 +63,16 @@ Understand anything (no build needed)
61
63
  reverseport binary <file> PE/.NET/ELF/Mach-O/wasm/class/dex at a glance
62
64
  reverseport archive <file> Godot .pck (also inside .exe), zip/apk/jar, tar.gz, asar — list or extract
63
65
  reverseport diff <a> <b> what changed between two builds, packs or binaries
66
+ reverseport refs <unity-project> broken Unity GUID references, duplicate and missing .meta files
67
+ reverseport strings <folder> extract translatable text (.pot/.csv); --action apply writes a translated copy
68
+ reverseport decode <folder|file> Godot export → .gd/.tscn/.tres/project.godot (after re_archive extract)
69
+ reverseport il2cpp <global-metadata.dat> Unity IL2CPP: classes, methods, literals, C# skeleton
70
+ reverseport apicheck <file|folder> Godot 3 names, invented members, too-new classes; --engine godot@4.3
71
+ reverseport upgrade <godot3-project> Godot 3 → 4 as a copy; --action apply --out <folder>; lists what needs a human
72
+ reverseport save <file> [other] save file: layers, fields with roles, checksums, diff against another save; --action schema
73
+ reverseport shader <file> <godot|threejs|unity> first draft of a shader in another engine, leftovers listed
74
+ reverseport rpgmaker <project> [out] RPG Maker MV/MZ → runnable Godot 4 project + list of what is left
75
+ reverseport trace harness <engine> | trace compare --a <json> --b <json> prove behaviour parity per tick
64
76
  reverseport report <folder> ARCHITECTURE.md
65
77
  reverseport port help every ReversePort command and option
66
78
 
@@ -1,7 +1,7 @@
1
- import { createWebScreenshotArtifact } from "../domain/webScreenshot.js";
1
+ import { createWebScreenshotArtifact, WEB_ELEMENT_HTML_LIMIT, WEB_ELEMENT_STYLE_LIMIT, } from "../domain/webScreenshot.js";
2
2
  import { BrowserObservationError } from "../domain/browserObservationError.js";
3
3
  import { isMainFrameNavigation } from "./CdpCaptureEventHelpers.js";
4
- import { allowedSanitizedUrl, recordValue, cdpStringValue, } from "./CdpCaptureValues.js";
4
+ import { allowedSanitizedUrl, recordValue, recordsValue, cdpStringValue, numberValue, } from "./CdpCaptureValues.js";
5
5
  import { mainFrameUrl } from "./CdpCaptureDocuments.js";
6
6
  import { captureFrames } from "./CdpCaptureDocuments.js";
7
7
  import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
@@ -36,12 +36,22 @@ export const captureCdpScreenshot = async (context) => {
36
36
  });
37
37
  let result;
38
38
  let after;
39
+ let element;
39
40
  try {
40
- result = recordValue(await context.connection.send("Page.captureScreenshot", { format: "png", fromSurface: true, captureBeyondViewport: false }, context.sessionId, context.signal));
41
+ if (context.input.selector !== undefined)
42
+ element = await probeElement(context, context.input.selector);
43
+ result = recordValue(await context.connection.send("Page.captureScreenshot", {
44
+ format: "png",
45
+ fromSurface: true,
46
+ captureBeyondViewport: false,
47
+ ...(element === undefined ? {} : { clip: element.clip }),
48
+ }, context.sessionId, context.signal));
41
49
  after = await context.connection.send("Page.getFrameTree", {}, context.sessionId, context.signal);
42
50
  }
43
51
  finally {
44
52
  removeListener();
53
+ if (context.input.selector !== undefined)
54
+ await releaseDomains(context);
45
55
  }
46
56
  const encoded = cdpStringValue(result?.data);
47
57
  const bytes = encoded === undefined ? undefined : decodeCanonicalBase64(encoded);
@@ -70,15 +80,133 @@ export const captureCdpScreenshot = async (context) => {
70
80
  origin: authorized.origin ?? "",
71
81
  },
72
82
  captured_at: new Date().toISOString(),
73
- viewport: dimensions,
83
+ viewport: element === undefined ? dimensions : element.viewport,
74
84
  artifact: createWebScreenshotArtifact(bytes),
85
+ ...(element === undefined
86
+ ? {}
87
+ : { element: { ...element.element, image: dimensions } }),
75
88
  completeness: new CdpCaptureCompleteness().snapshot(),
76
89
  limitations: [
77
- "The screenshot contains the visible viewport, including on-screen content.",
90
+ ...(element === undefined
91
+ ? [
92
+ "The screenshot contains the visible viewport, including on-screen content.",
93
+ ]
94
+ : [
95
+ "The image shows only the part of the element inside the viewport; scroll it into view in the browser for the rest.",
96
+ "outer_html is the element's markup as the page has it now, including attribute values.",
97
+ ]),
78
98
  "REA does not scroll, evaluate JavaScript, or capture beyond the current viewport.",
79
99
  ],
80
100
  };
81
101
  };
102
+ /** Find one element and read its box, markup and style via DOM and CSS. */
103
+ const probeElement = async (context, selector) => {
104
+ const send = (method, params = {}) => context.connection.send(method, params, context.sessionId, context.signal);
105
+ const notFound = (detail) => new BrowserObservationError("capture_web_screenshot", "target_not_found", {
106
+ detail,
107
+ });
108
+ const quoted = JSON.stringify(selector);
109
+ await send("DOM.enable");
110
+ await send("CSS.enable");
111
+ const tree = recordValue(await send("DOM.getDocument", { depth: 0 }));
112
+ const root = numberValue(recordValue(tree?.root)?.nodeId);
113
+ if (root === undefined)
114
+ throw new BrowserObservationError("capture_web_screenshot", "protocol_error");
115
+ const match = recordValue(await send("DOM.querySelector", { nodeId: root, selector }));
116
+ const nodeId = numberValue(match?.nodeId);
117
+ if (nodeId === undefined || nodeId === 0)
118
+ throw notFound(`No element matches the selector ${quoted} on this page.`);
119
+ const model = recordValue(recordValue(await send("DOM.getBoxModel", { nodeId }))?.model);
120
+ const box = quadBox(model?.border);
121
+ const metrics = recordValue(await send("Page.getLayoutMetrics"));
122
+ const layout = recordValue(metrics?.cssLayoutViewport);
123
+ const viewportWidth = numberValue(layout?.clientWidth);
124
+ const viewportHeight = numberValue(layout?.clientHeight);
125
+ if (box === undefined ||
126
+ viewportWidth === undefined ||
127
+ viewportHeight === undefined)
128
+ throw notFound(`The element for ${quoted} is not rendered.`);
129
+ const visible = intersect(box, {
130
+ x: 0,
131
+ y: 0,
132
+ width: viewportWidth,
133
+ height: viewportHeight,
134
+ });
135
+ if (visible === undefined)
136
+ throw notFound(`The element for ${quoted} is outside the visible viewport. Scroll it into view in the browser, then capture again.`);
137
+ const markup = recordValue(await send("DOM.getOuterHTML", { nodeId }));
138
+ const html = cdpStringValue(markup?.outerHTML) ?? "";
139
+ const computed = recordValue(await send("CSS.getComputedStyleForNode", { nodeId }));
140
+ const properties = recordsValue(computed?.computedStyle);
141
+ const style = {};
142
+ for (const property of properties.slice(0, WEB_ELEMENT_STYLE_LIMIT)) {
143
+ const name = cdpStringValue(property.name);
144
+ const value = cdpStringValue(property.value);
145
+ if (name !== undefined && value !== undefined)
146
+ style[name] = value;
147
+ }
148
+ return {
149
+ clip: {
150
+ x: visible.x + (numberValue(layout?.pageX) ?? 0),
151
+ y: visible.y + (numberValue(layout?.pageY) ?? 0),
152
+ width: visible.width,
153
+ height: visible.height,
154
+ scale: 1,
155
+ },
156
+ viewport: {
157
+ width: Math.max(1, Math.round(viewportWidth)),
158
+ height: Math.max(1, Math.round(viewportHeight)),
159
+ },
160
+ element: {
161
+ selector,
162
+ box,
163
+ visible_box: visible,
164
+ clipped: visible.width < box.width || visible.height < box.height,
165
+ outer_html: html.slice(0, WEB_ELEMENT_HTML_LIMIT),
166
+ outer_html_truncated: html.length > WEB_ELEMENT_HTML_LIMIT,
167
+ computed_style: style,
168
+ computed_style_truncated: properties.length > WEB_ELEMENT_STYLE_LIMIT,
169
+ },
170
+ };
171
+ };
172
+ /** Bounding box of a CDP quad (x1, y1, … x4, y4). */
173
+ const quadBox = (quad) => {
174
+ if (!Array.isArray(quad))
175
+ return undefined;
176
+ const numbers = quad.flatMap((item) => {
177
+ const value = numberValue(item);
178
+ return value === undefined ? [] : [value];
179
+ });
180
+ if (numbers.length !== 8)
181
+ return undefined;
182
+ const xs = numbers.filter((_, index) => index % 2 === 0);
183
+ const ys = numbers.filter((_, index) => index % 2 === 1);
184
+ const x = Math.min(...xs);
185
+ const y = Math.min(...ys);
186
+ const width = Math.max(...xs) - x;
187
+ const height = Math.max(...ys) - y;
188
+ return width > 0 && height > 0 ? { x, y, width, height } : undefined;
189
+ };
190
+ const intersect = (a, b) => {
191
+ const x = Math.max(a.x, b.x);
192
+ const y = Math.max(a.y, b.y);
193
+ const right = Math.min(a.x + a.width, b.x + b.width);
194
+ const bottom = Math.min(a.y + a.height, b.y + b.height);
195
+ return right - x >= 1 && bottom - y >= 1
196
+ ? { x, y, width: right - x, height: bottom - y }
197
+ : undefined;
198
+ };
199
+ /** Turn off the DOM and CSS domains this capture enabled; the session close handles the rest. */
200
+ const releaseDomains = async (context) => {
201
+ for (const method of ["CSS.disable", "DOM.disable"]) {
202
+ try {
203
+ await context.connection.send(method, {}, context.sessionId);
204
+ }
205
+ catch {
206
+ // Closing the target session below also ends these domains.
207
+ }
208
+ }
209
+ };
82
210
  const observeScreenshotNavigation = (event, mainFrameId, origins, state) => {
83
211
  if (!isMainFrameNavigation(event, mainFrameId))
84
212
  return;
@@ -92,13 +92,17 @@ const registerCaptureDiff = (cli, logger) => {
92
92
  };
93
93
  const registerScreenshot = (cli, logger) => {
94
94
  cli.command(CLI_COMMANDS.captureWebScreenshot, {
95
- description: "Capture one visible page viewport within the supplied origin scope",
95
+ description: "Capture one visible page viewport, or one element with --selector",
96
96
  args: z.object({
97
97
  endpoint: z.string().describe("Configured loopback CDP HTTP endpoint"),
98
98
  targetId: z.string().describe("Target ID from list-browser-targets"),
99
99
  }),
100
100
  options: z.object({
101
101
  ...browserScopeOptions,
102
+ selector: z
103
+ .string()
104
+ .optional()
105
+ .describe("CSS selector: crop to one element, add its HTML and CSS"),
102
106
  }),
103
107
  run: ({ args, options }) => logCliCommand(logger, "capture-web-screenshot", async () => {
104
108
  const context = browserContext();
@@ -106,6 +110,7 @@ const registerScreenshot = (cli, logger) => {
106
110
  cdp_endpoint: args.endpoint,
107
111
  allowed_origins: options.allowedOrigins,
108
112
  target_id: args.targetId,
113
+ selector: options.selector,
109
114
  });
110
115
  if (!parsed.success)
111
116
  return inputError("capture_web_screenshot");
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "./rolldown-runtime-DXoylpqc.js";
2
2
  import { init_jsonValue, jsonValueSchema } from "./providerOperationHealth-DSTcYPJe.js";
3
- import { init_relationshipCoverage, relationshipCoverageSchema } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
3
+ import { init_relationshipCoverage, relationshipCoverageSchema } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
4
4
 
5
5
  //#region dist/application/AnalysisProvider.js
6
6
  var createAnalysisExecution;
@@ -1,10 +1,10 @@
1
1
  import { __esmMin } from "./rolldown-runtime-DXoylpqc.js";
2
2
  import { AnalysisCancelledError, freezeJsonSnapshot, init_analysisErrorCore, init_immutableJson, init_jsonValue, jsonObjectSchema, jsonValueSchema } from "./providerOperationHealth-DSTcYPJe.js";
3
- import { BINARY_ARCHITECTURES, analysisProfileSchema, analysisProfilesEqual, canonicalJsonDigestSteps, committedProviderSchema, compareUnicodeCodePoints, compositeKey, digestSchema, err, evidenceBundleForTarget, evidenceBundleSchema, evidenceLocationSchema, init_analysisProfile, init_binaryTargetTypes, init_canonicalJsonDigestSteps, init_digests, init_evidence, init_evidenceBundle, init_localPath, init_relationshipCoverage, init_result, init_unicodeCodePointOrder, localPathStringSchema, ok, parseEvidenceBundle, parseImmutableEvidenceBundle, prefixedDigestSchema, rebindEvidenceToTargetPath, relationshipCoverageSchema } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
3
+ import { BINARY_ARCHITECTURES, analysisProfileSchema, analysisProfilesEqual, canonicalJsonDigestSteps, committedProviderSchema, compareUnicodeCodePoints, compositeKey, digestSchema, err, evidenceBundleForTarget, evidenceBundleSchema, evidenceLocationSchema, init_analysisProfile, init_binaryTargetTypes, init_canonicalJsonDigestSteps, init_digests, init_evidence, init_evidenceBundle, init_localPath, init_relationshipCoverage, init_result, init_unicodeCodePointOrder, localPathStringSchema, ok, parseEvidenceBundle, parseImmutableEvidenceBundle, prefixedDigestSchema, rebindEvidenceToTargetPath, relationshipCoverageSchema } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
4
4
  import { EvidenceIntegrityError, init_evidenceErrors } from "./analysisErrorPresentation-DZrKL8kS.js";
5
- import { init_rawBinary, rawBinaryEntryPointSchema } from "./toolEffects-DW31yTSx.js";
5
+ import { init_rawBinary, rawBinaryEntryPointSchema } from "./toolEffects-JovaVppR.js";
6
6
  import { RegularFileCleanupFailure, init_RegularFileRead } from "./RegularFileRead-BMh5FMXd.js";
7
- import { init_JsonFiles, readJsonObjectMembersFile, writeTextFile } from "./JsonFiles-Ce_O5NcH.js";
7
+ import { init_JsonFiles, readJsonObjectMembersFile, writeTextFile } from "./JsonFiles-v2nnQzBz.js";
8
8
  import { createHash } from "node:crypto";
9
9
  import { z } from "zod";
10
10
  import canonicalize from "canonicalize";
@@ -1,11 +1,11 @@
1
1
  import { __esmMin } from "./rolldown-runtime-DXoylpqc.js";
2
2
  import { AnalysisCancelledError, init_analysisErrorCore } from "./providerOperationHealth-DSTcYPJe.js";
3
- import { err, hasZipSignature, init_localPath, init_result, init_zipPackageFormat, isPathWithinRoot, isZipPackageFormat, ok, zipPackageFormatForPath } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
3
+ import { err, hasZipSignature, init_localPath, init_result, init_zipPackageFormat, isPathWithinRoot, isZipPackageFormat, ok, zipPackageFormatForPath } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
4
4
  import { BinaryTargetError, init_configurationErrors } from "./configurationErrors-ByuF6gMR.js";
5
- import { admitRawBinary, init_rawBinary, rawBinarySelectionError } from "./toolEffects-DW31yTSx.js";
6
- import { init_dosMz, mzWindowsHeaderOffset, parseDosMzHeader } from "./dosMz-pwwUuxyC.js";
5
+ import { admitRawBinary, init_rawBinary, rawBinarySelectionError } from "./toolEffects-JovaVppR.js";
6
+ import { init_dosMz, mzWindowsHeaderOffset, parseDosMzHeader } from "./dosMz-BZKOsUf9.js";
7
7
  import { init_RegularFile, openRegularFile, sameRegularFileState } from "./RegularFile-CL6meBxi.js";
8
- import { init_dosCom, validateDosComLength } from "./managedToolContracts-BSy4TRaK.js";
8
+ import { init_dosCom, validateDosComLength } from "./managedToolContracts-_YDzyE2p.js";
9
9
  import { decodeXmlPlistText, init_InterfaceBuilderDecodeBudget, init_propertyListXmlText, preflightPropertyListDecode } from "./InterfaceBuilderDecodeBudget-DT74BY9z.js";
10
10
  import { init_propertyListKeys, omitPrototypeKeys, parseXmlPropertyList } from "./propertyListKeys-DejfMb-U.js";
11
11
  import { extname, isAbsolute, join, resolve } from "node:path";
@@ -1,8 +1,8 @@
1
1
  import { __esmMin } from "./rolldown-runtime-DXoylpqc.js";
2
- import { PRODUCT_IDENTITY, compareUnicodeCodePoints, err, init_identity, init_result, init_unicodeCodePointOrder, ok } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
2
+ import { PRODUCT_IDENTITY, compareUnicodeCodePoints, err, init_identity, init_result, init_unicodeCodePointOrder, ok } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
3
3
  import { ArtifactReaderFailure, init_ArtifactReader } from "./ArtifactReader-BXkffc1D.js";
4
4
  import { ConfigurationError, init_configurationErrors } from "./configurationErrors-ByuF6gMR.js";
5
- import { clientSkillDirectories, init_SupportedClients, init_environment, parseEnvironment } from "./SupportedClients-BrZ2qZVg.js";
5
+ import { clientSkillDirectories, init_SupportedClients, init_environment, parseEnvironment } from "./SupportedClients-Cag4oXyu.js";
6
6
  import { NonRegularFileReadError, RegularFileChangedError, init_RegularFile } from "./RegularFile-CL6meBxi.js";
7
7
  import { init_BoundedFileBytes, readBoundedFileBytes } from "./BoundedFileBytes-BU30odTm.js";
8
8
  import { RegularFileCleanupFailure, init_RegularFileRead, withRegularFile } from "./RegularFileRead-BMh5FMXd.js";
@@ -1,10 +1,10 @@
1
1
  import { __esmMin } from "./rolldown-runtime-DXoylpqc.js";
2
- import { PRODUCT_IDENTITY, compareUnicodeCodePoints, err, init_identity, init_result, init_unicodeCodePointOrder, ok } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
2
+ import { PRODUCT_IDENTITY, compareUnicodeCodePoints, err, init_identity, init_result, init_unicodeCodePointOrder, ok } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
3
3
  import { ConfigurationError, init_configurationErrors } from "./configurationErrors-ByuF6gMR.js";
4
- import { clientEvidencePaths, init_ClientRegistrationIdentity, init_SupportedClients, init_environment, isOwnedClientRegistrationCommand, manualRegistrationRemediation, npxRegistrationCommand, packageRunnerRegistrationCommand, parseEnvironment, supportedClients } from "./SupportedClients-BrZ2qZVg.js";
4
+ import { clientEvidencePaths, init_ClientRegistrationIdentity, init_SupportedClients, init_environment, isOwnedClientRegistrationCommand, manualRegistrationRemediation, npxRegistrationCommand, packageRunnerRegistrationCommand, parseEnvironment, supportedClients } from "./SupportedClients-Cag4oXyu.js";
5
5
  import { RegularFileCleanupFailure, init_RegularFileRead, readRegularFileText } from "./RegularFileRead-BMh5FMXd.js";
6
6
  import { MCP_STARTUP_POLICY, init_mcpStartupPolicy } from "./mcpStartupPolicy-Bb7TMLzn.js";
7
- import { clientConfigurationValuesEqual, clientRegistrationEntry, clientServerForcedEnabled, clientServerListedDisabled, dshDocument, effectiveClientServer, geminiServerPolicyBlock, init_ClientConfigurationDocument, init_DshCordisPatch, parseClientConfiguration, parseGeminiMcpPolicy } from "./ClientConfigurationDocument-D0ZqgTCv.js";
7
+ import { clientConfigurationValuesEqual, clientRegistrationEntry, clientServerForcedEnabled, clientServerListedDisabled, dshDocument, effectiveClientServer, geminiServerPolicyBlock, init_ClientConfigurationDocument, init_DshCordisPatch, parseClientConfiguration, parseGeminiMcpPolicy } from "./ClientConfigurationDocument-BvmXMdrN.js";
8
8
  import { dirname, resolve } from "node:path";
9
9
  import { z } from "zod";
10
10
  import { access, realpath } from "node:fs/promises";
@@ -1,16 +1,16 @@
1
1
  import { __esmMin, __exportAll } from "./rolldown-runtime-DXoylpqc.js";
2
2
  import { AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisOutputError, init_analysisErrorCore, init_jsonValue, jsonValueSchema } from "./providerOperationHealth-DSTcYPJe.js";
3
- import { analysisProfileSchema, artifactInspectionResultSchema, committedProviderSchema, createEvidence, err, init_analysisProfile, init_artifactInspection, init_evidence, init_result, ok } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
3
+ import { analysisProfileSchema, artifactInspectionResultSchema, committedProviderSchema, createEvidence, err, init_analysisProfile, init_artifactInspection, init_evidence, init_result, ok } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
4
4
  import { ProviderAdapterError, init_providerAdapterError } from "./providerAdapterError-SRSE_gzN.js";
5
5
  import { EvidenceFileError, EvidenceIntegrityError, UnknownRegistryError, init_evidenceErrors, init_unknownRegistryError } from "./analysisErrorPresentation-DZrKL8kS.js";
6
6
  import { init_analysisErrorProjection, projectAnalysisError } from "./streamedJsonOutput-VYlQZsM7.js";
7
- import { addressedValue, analysisErrorProjectionSchema, init_errorSchemas, init_toolOutputSchemaPrimitives } from "./toolEffects-DW31yTSx.js";
8
- import { REA_WORKFLOW_PROVIDER, init_InvestigationProviders, workflowAnalysisProfile } from "./InvestigationProviders-D-QCy-4c.js";
7
+ import { addressedValue, analysisErrorProjectionSchema, init_errorSchemas, init_toolOutputSchemaPrimitives } from "./toolEffects-JovaVppR.js";
8
+ import { REA_WORKFLOW_PROVIDER, init_InvestigationProviders, workflowAnalysisProfile } from "./InvestigationProviders-DhwicuUg.js";
9
9
  import { init_logger, silentLogger } from "./logger-CKq3JfbZ.js";
10
- import { init_managedToolContracts, isManagedToolName } from "./managedToolContracts-BSy4TRaK.js";
10
+ import { init_managedToolContracts, isManagedToolName } from "./managedToolContracts-_YDzyE2p.js";
11
11
  import { analysisErrorWithCleanupFailure, init_analysisErrorCleanup } from "./analysisErrorCleanup-DaUQNiQd.js";
12
- import { init_BinaryTargetResolver, parseBinaryTarget } from "./BinaryTargetResolver-CKRfFhLj.js";
13
- import { init_AnalysisSnapshotFiles, init_analysisSnapshot, readAnalysisSnapshot, snapshotEvidenceForQuery, snapshotMatchesTarget } from "./AnalysisSnapshotFiles-BuK_ymw5.js";
12
+ import { init_BinaryTargetResolver, parseBinaryTarget } from "./BinaryTargetResolver-uNu5jLfD.js";
13
+ import { init_AnalysisSnapshotFiles, init_analysisSnapshot, readAnalysisSnapshot, snapshotEvidenceForQuery, snapshotMatchesTarget } from "./AnalysisSnapshotFiles-CpXtlUrr.js";
14
14
  import { access } from "node:fs/promises";
15
15
 
16
16
  //#region dist/application/WorkflowEvidence.js
@@ -382,7 +382,7 @@ function init_DirectAnalysis() {
382
382
  executeAnalysisTool = async (input) => {
383
383
  const { session, tool, signal, evidenceProfile } = input;
384
384
  if (tool === "analyze_function") {
385
- const { executeFunctionAnalysisEvidence } = await import("./application__FunctionAnalysisEvidence-fWSgvV74.js");
385
+ const { executeFunctionAnalysisEvidence } = await import("./application__FunctionAnalysisEvidence-DWYRXeqm.js");
386
386
  const result = await executeFunctionAnalysisEvidence(session, input.arguments, input.openedTarget, { signal });
387
387
  return result.ok ? {
388
388
  output: result.value,
@@ -390,7 +390,7 @@ function init_DirectAnalysis() {
390
390
  } : { output: cliError(result.error) };
391
391
  }
392
392
  if (tool === "binary_overview" || tool === "inspect_native_api" || tool === "inspect_native_dispatch_metadata" || tool === "trace_feature" || tool === "trace_native_values" || tool === "trace_native_ui_action") {
393
- const { EnhancedTools } = await import("./application__EnhancedTools-C__HAdqG.js");
393
+ const { EnhancedTools } = await import("./application__EnhancedTools-BRAWz8_S.js");
394
394
  const result = await new EnhancedTools(session).execute(tool, input.arguments, signal);
395
395
  if (!result.ok) return { output: cliError(result.error) };
396
396
  const evidence = createWorkflowEvidence({
@@ -1,15 +1,15 @@
1
1
  import { __esmMin, __exportAll } from "./rolldown-runtime-DXoylpqc.js";
2
- import { PRODUCT_IDENTITY, SDK_IDENTITY, init_canonicalOrdering, init_identity, uniqueSorted } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
2
+ import { PRODUCT_IDENTITY, SDK_IDENTITY, init_canonicalOrdering, init_identity, uniqueSorted } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
3
3
  import { BinaryTargetError, init_configurationErrors } from "./configurationErrors-ByuF6gMR.js";
4
4
  import { analysisErrorRemediationAction, init_analysisErrorPresentation } from "./analysisErrorPresentation-DZrKL8kS.js";
5
5
  import { execFileOutput, init_ExecFileOutput } from "./ExecFileOutput-Czbj-HpV.js";
6
- import { homeDirectoryFromEnvironment, init_SupportedClients, init_homeDirectory, manualRegistrationRemediation } from "./SupportedClients-BrZ2qZVg.js";
6
+ import { homeDirectoryFromEnvironment, init_SupportedClients, init_homeDirectory, manualRegistrationRemediation } from "./SupportedClients-Cag4oXyu.js";
7
7
  import { ArtifactResourceScope, init_ArtifactResourceScope } from "./ArtifactResourceScope-CZqLEfbb.js";
8
- import { init_BinaryTargetResolver, parseBinaryTarget } from "./BinaryTargetResolver-CKRfFhLj.js";
8
+ import { init_BinaryTargetResolver, parseBinaryTarget } from "./BinaryTargetResolver-uNu5jLfD.js";
9
9
  import { SUPPORTED_NODE_VERSION_PROSE, init_runtimeVersion, javaScriptRuntime, supportsNodeVersion } from "./runtimeVersion-CMGd0bDu.js";
10
- import { CATALOG_IDENTITY, init_catalogIdentity } from "./catalogIdentity-EYVhBUYJ.js";
11
- import { init_SetupSkill, readInstalledSkillIdentity } from "./ClientConfigurationDocument-D0ZqgTCv.js";
12
- import { init_ClientRegistrationStatus, readClientRegistrationStatuses } from "./ClientRegistrationStatus-DGpwJ4ry.js";
10
+ import { CATALOG_IDENTITY, init_catalogIdentity } from "./catalogIdentity-D843Oy_i.js";
11
+ import { init_SetupSkill, readInstalledSkillIdentity } from "./ClientConfigurationDocument-BvmXMdrN.js";
12
+ import { init_ClientRegistrationStatus, readClientRegistrationStatuses } from "./ClientRegistrationStatus-BiBrkFVM.js";
13
13
  import { join } from "node:path";
14
14
  import { createHash } from "node:crypto";
15
15
  import { z } from "zod";
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "./rolldown-runtime-DXoylpqc.js";
2
2
  import { AnalysisCancelledError, AnalysisError, init_analysisErrorBase, init_analysisErrorCore } from "./providerOperationHealth-DSTcYPJe.js";
3
- import { WEB_RUNTIME_LIMITS, classifyBrowserCompleteness, compareUnicodeCodePoints, createWebTextArtifact, init_browserCompleteness, init_browserObservation, init_unicodeCodePointOrder, init_webContentArtifact, init_webRuntime, sanitizeBrowserUrl } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
3
+ import { WEB_RUNTIME_LIMITS, classifyBrowserCompleteness, compareUnicodeCodePoints, createWebTextArtifact, init_browserCompleteness, init_browserObservation, init_unicodeCodePointOrder, init_webContentArtifact, init_webRuntime, sanitizeBrowserUrl } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
4
4
  import { BrowserObservationError, init_browserObservationError } from "./browserObservationError-D73SM55P.js";
5
5
  import { init_safeJson, safeParseJson } from "./safeJson-DKKACtdy.js";
6
6
  import { MAX_ASAR_HEADER_BYTES, admitAsarHeader, init_AsarHeader } from "./AsarHeader-CnzOzYEH.js";
@@ -1,11 +1,11 @@
1
1
  import { __esmMin } from "./rolldown-runtime-DXoylpqc.js";
2
2
  import { hopperStartupExitCode, init_hopperStartupFailure, isHopperStartupFailureCode } from "./providerOperationHealth-DSTcYPJe.js";
3
- import { err, init_binaryTargetTypes, init_result, isMachOFormat, ok } from "./reconstructionObligationLedgerSchemas-dvp6PEnZ.js";
3
+ import { err, init_binaryTargetTypes, init_result, isMachOFormat, ok } from "./reconstructionObligationLedgerSchemas-CBxjNJ5m.js";
4
4
  import { ConfigurationError, init_configurationErrors } from "./configurationErrors-ByuF6gMR.js";
5
- import { ProviderProcessSupervisor, init_ProviderProcess, init_snapshotEnvironment, snapshotEnvironment, spawnOwnedProviderProcess } from "./snapshotEnvironment-B5Ai0mha.js";
6
- import { cleanupOwnedProcessGroup, init_ProcessOwnership } from "./ProcessOwnership-AOJaszxt.js";
5
+ import { ProviderProcessSupervisor, init_ProviderProcess, init_snapshotEnvironment, snapshotEnvironment, spawnOwnedProviderProcess } from "./snapshotEnvironment-CF3KJGdj.js";
6
+ import { cleanupOwnedProcessGroup, init_ProcessOwnership } from "./ProcessOwnership-Ddlg82OS.js";
7
7
  import { init_safeJson, safeParseJson } from "./safeJson-DKKACtdy.js";
8
- import { init_binaryTarget, parseExecutableHeader } from "./BinaryTargetResolver-CKRfFhLj.js";
8
+ import { init_binaryTarget, parseExecutableHeader } from "./BinaryTargetResolver-uNu5jLfD.js";
9
9
  import { isAbsolute, posix, win32 } from "node:path";
10
10
  import { randomUUID } from "node:crypto";
11
11
  import { z } from "zod";