@eyeauras/insight-cli 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cli-package-build.json +1 -1
- package/README.md +33 -2
- package/SKILL.md +38 -51
- package/dist/src/administration-results.js +1 -1
- package/dist/src/administration.d.ts +1 -1
- package/dist/src/administration.js +16 -2
- package/dist/src/binary.d.ts +3 -0
- package/dist/src/binary.js +74 -0
- package/dist/src/capture.d.ts +3 -0
- package/dist/src/capture.js +220 -0
- package/dist/src/cli.js +91 -14
- package/dist/src/contexts.d.ts +5 -0
- package/dist/src/contexts.js +54 -18
- package/dist/src/debugger-caller.d.ts +17 -0
- package/dist/src/debugger-caller.js +129 -0
- package/dist/src/debugger-launch.d.ts +2 -0
- package/dist/src/debugger-launch.js +17 -0
- package/dist/src/debugger-results.d.ts +1 -0
- package/dist/src/debugger-results.js +8 -0
- package/dist/src/debugger-supervisor.js +56 -13
- package/dist/src/debugger.js +16 -7
- package/dist/src/die.d.ts +12 -0
- package/dist/src/die.js +127 -0
- package/dist/src/dnspy-runtime.d.ts +8 -0
- package/dist/src/dnspy-runtime.js +46 -0
- package/dist/src/dnspy.d.ts +22 -0
- package/dist/src/dnspy.js +160 -0
- package/dist/src/dotnet-diagnostics.d.ts +13 -0
- package/dist/src/dotnet-diagnostics.js +101 -0
- package/dist/src/frida-worker.d.ts +1 -0
- package/dist/src/frida-worker.js +125 -0
- package/dist/src/frida.d.ts +16 -0
- package/dist/src/frida.js +125 -0
- package/dist/src/ghidra-debugger-runtime.d.ts +7 -0
- package/dist/src/ghidra-debugger-runtime.js +31 -0
- package/dist/src/ghidra-processes.d.ts +6 -0
- package/dist/src/ghidra-processes.js +121 -0
- package/dist/src/ghidra.js +6 -6
- package/dist/src/ilspy.d.ts +7 -0
- package/dist/src/ilspy.js +122 -0
- package/dist/src/lifecycle.d.ts +1 -1
- package/dist/src/lifecycle.js +8 -2
- package/dist/src/lldb.d.ts +10 -0
- package/dist/src/lldb.js +99 -0
- package/dist/src/llvm.d.ts +6 -0
- package/dist/src/llvm.js +133 -0
- package/dist/src/managed-heap.d.ts +4 -0
- package/dist/src/managed-heap.js +73 -0
- package/dist/src/managed-metadata.d.ts +11 -0
- package/dist/src/managed-metadata.js +66 -0
- package/dist/src/mitmproxy.d.ts +55 -0
- package/dist/src/mitmproxy.js +172 -0
- package/dist/src/native-inputs.d.ts +3 -2
- package/dist/src/native-inputs.js +21 -5
- package/dist/src/package-version.d.ts +1 -0
- package/dist/src/package-version.js +3 -0
- package/dist/src/procmon-config.d.ts +2 -0
- package/dist/src/procmon-config.js +15 -0
- package/dist/src/procmon-events.d.ts +13 -0
- package/dist/src/procmon-events.js +82 -0
- package/dist/src/procmon.d.ts +4 -0
- package/dist/src/procmon.js +107 -0
- package/dist/src/research.d.ts +11 -2
- package/dist/src/research.js +5 -3
- package/dist/src/runtime-catalog.d.ts +13 -0
- package/dist/src/runtime-catalog.js +26 -0
- package/dist/src/runtime-manager.d.ts +125 -0
- package/dist/src/runtime-manager.js +385 -0
- package/dist/src/runtime-selection.d.ts +13 -0
- package/dist/src/runtime-selection.js +42 -0
- package/dist/src/server.d.ts +15 -0
- package/dist/src/server.js +77 -96
- package/dist/src/sevenzip.d.ts +15 -0
- package/dist/src/sevenzip.js +119 -0
- package/dist/src/strace.d.ts +10 -0
- package/dist/src/strace.js +71 -0
- package/dist/src/text-window.d.ts +11 -0
- package/dist/src/text-window.js +6 -0
- package/dist/src/tool-runtime/archives.d.ts +10 -0
- package/dist/src/tool-runtime/archives.js +194 -0
- package/dist/src/tool-runtime/catalog.d.ts +3 -0
- package/dist/src/tool-runtime/catalog.js +13 -0
- package/dist/src/tool-runtime/commands.d.ts +9 -0
- package/dist/src/tool-runtime/commands.js +39 -0
- package/dist/src/tool-runtime/deadline.d.ts +11 -0
- package/dist/src/tool-runtime/deadline.js +32 -0
- package/dist/src/tool-runtime/definition.d.ts +73 -0
- package/dist/src/tool-runtime/definition.js +49 -0
- package/dist/src/tool-runtime/dotnet.d.ts +4 -0
- package/dist/src/tool-runtime/dotnet.js +22 -0
- package/dist/src/tool-runtime/identity.d.ts +6 -0
- package/dist/src/tool-runtime/identity.js +50 -0
- package/dist/src/tool-runtime/installer.d.ts +101 -0
- package/dist/src/tool-runtime/installer.js +180 -0
- package/dist/src/tool-runtime/launch-worker.d.ts +1 -0
- package/dist/src/tool-runtime/launch-worker.js +58 -0
- package/dist/src/tool-runtime/run.d.ts +51 -0
- package/dist/src/tool-runtime/run.js +159 -0
- package/dist/src/tool-runtime/store.d.ts +15 -0
- package/dist/src/tool-runtime/store.js +219 -0
- package/dist/src/tool-runtime/supervisor.d.ts +57 -0
- package/dist/src/tool-runtime/supervisor.js +266 -0
- package/dist/src/tool-runtime/windows-job.d.ts +22 -0
- package/dist/src/tool-runtime/windows-job.js +43 -0
- package/dist/src/toolbox.d.ts +84 -0
- package/dist/src/toolbox.js +35 -0
- package/dist/src/tshark.d.ts +23 -0
- package/dist/src/tshark.js +174 -0
- package/dist/src/windbg.d.ts +14 -0
- package/dist/src/windbg.js +119 -0
- package/dist/src/workspace.d.ts +1 -0
- package/dist/src/workspace.js +6 -0
- package/package.json +7 -4
- package/references/administration.md +2 -1
- package/references/agent-execution.md +36 -0
- package/references/agent-setup.md +61 -0
- package/references/artifacts.md +5 -0
- package/references/debugger.md +22 -0
- package/references/ilspy.md +33 -0
- package/references/managed-runtime.md +157 -0
- package/references/native/InsightPythonWheels.java +283 -2
- package/references/native/InsightRuntimeDoctor.java +33 -0
- package/references/native/InsightTraceState.java +28 -13
- package/references/setup.md +6 -3
- package/runtime/managed/insight-heap/Azure.Core.dll +0 -0
- package/runtime/managed/insight-heap/Azure.Identity.dll +0 -0
- package/runtime/managed/insight-heap/Insight.Heap.csproj +1 -0
- package/runtime/managed/insight-heap/Insight.Heap.deps.json +391 -0
- package/runtime/managed/insight-heap/Insight.Heap.dll +0 -0
- package/runtime/managed/insight-heap/Insight.Heap.runtimeconfig.json +13 -0
- package/runtime/managed/insight-heap/Microsoft.Bcl.AsyncInterfaces.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Diagnostics.NETCore.Client.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Diagnostics.Runtime.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Configuration.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Diagnostics.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.FileProviders.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Hosting.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Options.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Extensions.Primitives.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Identity.Client.Extensions.Msal.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Identity.Client.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.IdentityModel.Abstractions.dll +0 -0
- package/runtime/managed/insight-heap/Microsoft.Security.AntiSSRF.dll +0 -0
- package/runtime/managed/insight-heap/NuGet.Config +1 -0
- package/runtime/managed/insight-heap/Program.cs +20 -0
- package/runtime/managed/insight-heap/README.md +16 -0
- package/runtime/managed/insight-heap/System.ClientModel.dll +0 -0
- package/runtime/managed/insight-heap/System.Memory.Data.dll +0 -0
- package/runtime/managed/insight-heap/System.Security.Cryptography.ProtectedData.dll +0 -0
- package/runtime/managed/insight-heap/dependencies.json +436 -0
- package/runtime/managed/insight-heap/notices/Azure.Core-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Azure.Identity-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.NETCore.Client-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.Runtime-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client.Extensions.Msal-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.IdentityModel.Abstractions-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/Microsoft.Security.AntiSSRF-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/System.ClientModel-LICENSE.txt +21 -0
- package/runtime/managed/insight-heap/notices/System.Memory.Data-LICENSE.txt +23 -0
- package/runtime/managed/insight-heap/notices/System.Memory.Data-THIRD-PARTY-NOTICES.TXT +1418 -0
- package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-LICENSE.TXT +23 -0
- package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-THIRD-PARTY-NOTICES.TXT +309 -0
- package/runtime/managed/insight-heap/packages.lock.json +165 -0
- package/runtime/managed/insight-heap/provenance.json +146 -0
- package/runtime/managed/insight-heap/runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll +0 -0
- package/runtime/managed/insight-managed/Insight.Managed.csproj +4 -0
- package/runtime/managed/insight-managed/Insight.Managed.deps.json +41 -0
- package/runtime/managed/insight-managed/Insight.Managed.dll +0 -0
- package/runtime/managed/insight-managed/Insight.Managed.runtimeconfig.json +13 -0
- package/runtime/managed/insight-managed/LICENSE.dnlib.txt +20 -0
- package/runtime/managed/insight-managed/NuGet.Config +1 -0
- package/runtime/managed/insight-managed/Program.cs +31 -0
- package/runtime/managed/insight-managed/README.md +16 -0
- package/runtime/managed/insight-managed/dnlib.dll +0 -0
- package/runtime/managed/insight-managed/packages.lock.json +13 -0
- package/runtime/managed/insight-managed/provenance.json +40 -0
- package/runtime/native/binary/README.md +22 -0
- package/runtime/native/binary/dependencies.json +166 -0
- package/runtime/native/binary/helper.cpp +44 -0
- package/runtime/native/binary/insight-binary-darwin-arm64 +0 -0
- package/runtime/native/binary/notices/Catch2-3.12.0--Catch2-3.12.0__LICENSE.txt +23 -0
- package/runtime/native/binary/notices/LIEF-LICENSE.txt +202 -0
- package/runtime/native/binary/notices/LIEF-attribution.txt +37 -0
- package/runtime/native/binary/notices/Melkor_ELF_Fuzzer-ac2495b--elf_fuzzer-master__LICENSE.txt +674 -0
- package/runtime/native/binary/notices/expected-1.3.1--expected-1.3.1__COPYING +121 -0
- package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__AUTHORS +3 -0
- package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__LICENSE +202 -0
- package/runtime/native/binary/notices/json-LICENSE.MIT +21 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--LICENSE +553 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--framework__LICENSE +553 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__LICENSE +552 -0
- package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__framework__LICENSE +553 -0
- package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--LICENSE +26 -0
- package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--ext__robin_map__LICENSE +21 -0
- package/runtime/native/binary/notices/span-LICENSE_1_0.txt +23 -0
- package/runtime/native/binary/notices/span-attribution.txt +11 -0
- package/runtime/native/binary/notices/spdlog-1.17.0--spdlog-1.17.0__LICENSE +25 -0
- package/runtime/native/binary/notices/utfcpp-4.0.9--utfcpp-4.0.9__LICENSE +23 -0
- package/runtime/native/binary/provenance.json +48 -0
- package/runtime/native/child-deadline-linux-x64 +0 -0
- package/runtime/native/child-deadline-linux.c +24 -0
- package/runtime/native/child-deadline-linux.provenance.json +17 -0
- package/runtime/native/deadline-alarm-darwin-universal.dylib +0 -0
- package/runtime/native/deadline-alarm.c +33 -0
- package/runtime/native/deadline-alarm.provenance.json +22 -0
- package/runtime/native/deadline-exec-darwin-arm64 +0 -0
- package/runtime/native/deadline-exec.c +24 -0
- package/runtime/native/deadline-exec.provenance.json +17 -0
- package/runtime/native/dnspy-extension/Bridge.cs +58 -0
- package/runtime/native/dnspy-extension/Insight.DnSpy.csproj +13 -0
- package/runtime/native/dnspy-extension/Insight.DnSpy.x.dll +0 -0
- package/runtime/native/dnspy-extension/NuGet.Config +1 -0
- package/runtime/native/dnspy-extension/UNICODE-LOADER.md +26 -0
- package/runtime/native/dnspy-extension/packages.lock.json +6 -0
- package/runtime/native/dnspy-extension/provenance.json +27 -0
- package/runtime/native/dnspy-extension/upstream-public-build.snk +0 -0
- package/runtime/native/dnspy-extension/vendor-files.json +4341 -0
- package/runtime/native/file-version.ps1 +7 -0
- package/runtime/native/insight-registry-win-x64.dll +0 -0
- package/runtime/native/mitmproxy/bridge.py +180 -0
- package/runtime/native/mitmproxy/notices.json +476 -0
- package/runtime/native/sources/detours-LICENSE.md +23 -0
- package/runtime/native/sources/detours-e4bfd6b.tar.gz +0 -0
- package/runtime/native/sources/detours-provenance.json +10 -0
- package/runtime/native/tshark-layout.json +2247 -0
- package/runtime/native/windows-job/DirectoryAlias.cs +24 -0
- package/runtime/native/windows-job/Insight.WindowsJob.csproj +1 -0
- package/runtime/native/windows-job/Insight.WindowsJob.dll +0 -0
- package/runtime/native/windows-job/NuGet.Config +1 -0
- package/runtime/native/windows-job/OwnedJob.cs +79 -0
- package/runtime/native/windows-job/RegistryRedirect.cs +45 -0
- package/runtime/native/windows-job/packages.lock.json +21 -0
- package/runtime/native/windows-job/provenance.json +16 -0
- package/runtime/native/windows-job/windows-job.ps1 +8 -0
- package/runtime/native/windows-registry.c +21 -0
- package/runtime/native/windows-registry.def +3 -0
- package/runtime/native/windows-registry.provenance.json +14 -0
- package/runtime/notices/diagnostics-10.0.750501.txt +23 -0
- package/runtime/tool-catalog.json +290 -0
- package/runtime/toolbox.json +1401 -0
- package/skill-bundle/insight-artifacts/SKILL.md +30 -0
- package/skill-bundle/insight-artifacts/references/agent-execution.md +36 -0
- package/skill-bundle/insight-artifacts/references/artifacts.md +52 -0
- package/skill-bundle/insight-binary/SKILL.md +46 -0
- package/skill-bundle/insight-binary/references/agent-execution.md +36 -0
- package/skill-bundle/insight-capture/SKILL.md +56 -0
- package/skill-bundle/insight-capture/references/agent-execution.md +36 -0
- package/skill-bundle/insight-cli/SKILL.md +42 -0
- package/skill-bundle/insight-cli/references/agent-execution.md +36 -0
- package/skill-bundle/insight-cli/references/agent-setup.md +61 -0
- package/skill-bundle/insight-die/SKILL.md +49 -0
- package/skill-bundle/insight-die/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dnspy/SKILL.md +65 -0
- package/skill-bundle/insight-dnspy/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dotnet-dump/SKILL.md +46 -0
- package/skill-bundle/insight-dotnet-dump/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dotnet-stack/SKILL.md +39 -0
- package/skill-bundle/insight-dotnet-stack/references/agent-execution.md +36 -0
- package/skill-bundle/insight-dotnet-trace/SKILL.md +45 -0
- package/skill-bundle/insight-dotnet-trace/references/agent-execution.md +36 -0
- package/skill-bundle/insight-frida/SKILL.md +67 -0
- package/skill-bundle/insight-frida/references/agent-execution.md +36 -0
- package/skill-bundle/insight-ghidra/SKILL.md +91 -0
- package/skill-bundle/insight-ghidra/references/administration.md +34 -0
- package/skill-bundle/insight-ghidra/references/agent-execution.md +36 -0
- package/skill-bundle/insight-ghidra/references/archive.md +32 -0
- package/skill-bundle/insight-ghidra/references/artifacts.md +52 -0
- package/skill-bundle/insight-ghidra/references/debugger.md +62 -0
- package/skill-bundle/insight-ghidra/references/extensions-and-sync.md +124 -0
- package/skill-bundle/insight-ghidra/references/managed-runtime.md +157 -0
- package/skill-bundle/insight-ghidra/references/native-workflows.md +112 -0
- package/skill-bundle/insight-ghidra/references/query-semantics.md +96 -0
- package/skill-bundle/insight-ghidra/references/recovery.md +53 -0
- package/skill-bundle/insight-ghidra/references/research.md +101 -0
- package/skill-bundle/insight-ghidra/references/setup.md +50 -0
- package/skill-bundle/insight-ilspy/SKILL.md +45 -0
- package/skill-bundle/insight-ilspy/references/agent-execution.md +36 -0
- package/skill-bundle/insight-ilspy/references/ilspy.md +33 -0
- package/skill-bundle/insight-interop/SKILL.md +54 -0
- package/skill-bundle/insight-interop/references/agent-execution.md +36 -0
- package/skill-bundle/insight-lldb/SKILL.md +54 -0
- package/skill-bundle/insight-lldb/references/agent-execution.md +36 -0
- package/skill-bundle/insight-llvm/SKILL.md +56 -0
- package/skill-bundle/insight-llvm/references/agent-execution.md +36 -0
- package/skill-bundle/insight-managed-heap/SKILL.md +43 -0
- package/skill-bundle/insight-managed-heap/references/agent-execution.md +36 -0
- package/skill-bundle/insight-managed-metadata/SKILL.md +52 -0
- package/skill-bundle/insight-managed-metadata/references/agent-execution.md +36 -0
- package/skill-bundle/insight-mitmproxy/SKILL.md +62 -0
- package/skill-bundle/insight-mitmproxy/references/agent-execution.md +36 -0
- package/skill-bundle/insight-overview/SKILL.md +79 -0
- package/skill-bundle/insight-overview/references/agent-execution.md +36 -0
- package/skill-bundle/insight-procmon/SKILL.md +49 -0
- package/skill-bundle/insight-procmon/references/agent-execution.md +36 -0
- package/skill-bundle/insight-re/SKILL.md +121 -0
- package/skill-bundle/insight-re/references/agent-execution.md +36 -0
- package/skill-bundle/insight-re/references/artifacts.md +52 -0
- package/skill-bundle/insight-re/references/recovery.md +53 -0
- package/skill-bundle/insight-sevenzip/SKILL.md +42 -0
- package/skill-bundle/insight-sevenzip/references/agent-execution.md +36 -0
- package/skill-bundle/insight-strace/SKILL.md +46 -0
- package/skill-bundle/insight-strace/references/agent-execution.md +36 -0
- package/skill-bundle/insight-tshark/SKILL.md +49 -0
- package/skill-bundle/insight-tshark/references/agent-execution.md +36 -0
- package/skill-bundle/insight-windbg/SKILL.md +46 -0
- package/skill-bundle/insight-windbg/references/agent-execution.md +36 -0
- package/skill-bundle/manifest.json +32 -0
- package/skills/insight-artifacts/SKILL.md +30 -0
- package/skills/insight-artifacts/references/agent-execution.md +36 -0
- package/skills/insight-artifacts/references/artifacts.md +52 -0
- package/skills/insight-binary/SKILL.md +46 -0
- package/skills/insight-binary/references/agent-execution.md +36 -0
- package/skills/insight-capture/SKILL.md +56 -0
- package/skills/insight-capture/references/agent-execution.md +36 -0
- package/skills/insight-die/SKILL.md +49 -0
- package/skills/insight-die/references/agent-execution.md +36 -0
- package/skills/insight-dnspy/SKILL.md +65 -0
- package/skills/insight-dnspy/references/agent-execution.md +36 -0
- package/skills/insight-dotnet-dump/SKILL.md +46 -0
- package/skills/insight-dotnet-dump/references/agent-execution.md +36 -0
- package/skills/insight-dotnet-stack/SKILL.md +39 -0
- package/skills/insight-dotnet-stack/references/agent-execution.md +36 -0
- package/skills/insight-dotnet-trace/SKILL.md +45 -0
- package/skills/insight-dotnet-trace/references/agent-execution.md +36 -0
- package/skills/insight-frida/SKILL.md +67 -0
- package/skills/insight-frida/references/agent-execution.md +36 -0
- package/skills/insight-ghidra/SKILL.md +91 -0
- package/skills/insight-ghidra/references/administration.md +34 -0
- package/skills/insight-ghidra/references/agent-execution.md +36 -0
- package/skills/insight-ghidra/references/archive.md +32 -0
- package/skills/insight-ghidra/references/artifacts.md +52 -0
- package/skills/insight-ghidra/references/debugger.md +62 -0
- package/skills/insight-ghidra/references/extensions-and-sync.md +124 -0
- package/skills/insight-ghidra/references/managed-runtime.md +157 -0
- package/skills/insight-ghidra/references/native-workflows.md +112 -0
- package/skills/insight-ghidra/references/query-semantics.md +96 -0
- package/skills/insight-ghidra/references/recovery.md +53 -0
- package/skills/insight-ghidra/references/research.md +101 -0
- package/skills/insight-ghidra/references/setup.md +50 -0
- package/skills/insight-ilspy/SKILL.md +45 -0
- package/skills/insight-ilspy/references/agent-execution.md +36 -0
- package/skills/insight-ilspy/references/ilspy.md +33 -0
- package/skills/insight-interop/SKILL.md +54 -0
- package/skills/insight-interop/references/agent-execution.md +36 -0
- package/skills/insight-lldb/SKILL.md +54 -0
- package/skills/insight-lldb/references/agent-execution.md +36 -0
- package/skills/insight-llvm/SKILL.md +56 -0
- package/skills/insight-llvm/references/agent-execution.md +36 -0
- package/skills/insight-managed-heap/SKILL.md +43 -0
- package/skills/insight-managed-heap/references/agent-execution.md +36 -0
- package/skills/insight-managed-metadata/SKILL.md +52 -0
- package/skills/insight-managed-metadata/references/agent-execution.md +36 -0
- package/skills/insight-mitmproxy/SKILL.md +62 -0
- package/skills/insight-mitmproxy/references/agent-execution.md +36 -0
- package/skills/insight-overview/SKILL.md +79 -0
- package/skills/insight-overview/references/agent-execution.md +36 -0
- package/skills/insight-procmon/SKILL.md +49 -0
- package/skills/insight-procmon/references/agent-execution.md +36 -0
- package/skills/insight-re/SKILL.md +22 -9
- package/skills/insight-re/references/agent-execution.md +36 -0
- package/skills/insight-re/references/artifacts.md +52 -0
- package/skills/insight-re/references/recovery.md +53 -0
- package/skills/insight-sevenzip/SKILL.md +42 -0
- package/skills/insight-sevenzip/references/agent-execution.md +36 -0
- package/skills/insight-strace/SKILL.md +46 -0
- package/skills/insight-strace/references/agent-execution.md +36 -0
- package/skills/insight-tshark/SKILL.md +49 -0
- package/skills/insight-tshark/references/agent-execution.md +36 -0
- package/skills/insight-windbg/SKILL.md +46 -0
- package/skills/insight-windbg/references/agent-execution.md +36 -0
package/.cli-package-build.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":1,"artifact":"
|
|
1
|
+
{"version":1,"artifact":"b65915991d87f45608bceba8cc7afa48b2e04f292149acf604aaf91ec2d2d6ba"}
|
package/README.md
CHANGED
|
@@ -17,14 +17,40 @@ The executable is `insight-cli`. Its global npm executable directory must be on
|
|
|
17
17
|
No source checkout, TypeScript build or separate Factory installation is required.
|
|
18
18
|
The pinned Factory IPC runtime is a normal npm dependency fetched from an immutable
|
|
19
19
|
GitHub tarball URL; installation therefore needs npm registry and GitHub access.
|
|
20
|
-
|
|
20
|
+
Use `insight-cli ghidra install` to deliver the pinned Ghidra/JDK/native/server runtime.
|
|
21
|
+
External Ghidra launchers and Java paths are also supported.
|
|
22
|
+
`insight-cli ilspy install` delivers ILSpy and its private .NET runtime for managed-code
|
|
23
|
+
research. Tool downloads use pinned assets retained in our GitHub Releases.
|
|
24
|
+
Use `insight-cli tools processes` to inspect owned executions across tools.
|
|
21
25
|
Help, skill discovery and saving ordinary files do not need Ghidra or Java.
|
|
22
26
|
|
|
27
|
+
Downloading a tool does not expose it in an agent's tool list. Connect the packaged skills
|
|
28
|
+
to your agent host, or explicitly give the agent the path returned by `insight-cli skill
|
|
29
|
+
insight-re --json`. See [agent setup](references/agent-setup.md) for tested project-local
|
|
30
|
+
Codex setup and a practical usability check. Installation leaves agent settings unchanged.
|
|
31
|
+
|
|
32
|
+
## Discover the toolbox
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
insight-cli tools list --json
|
|
36
|
+
insight-cli tools show die --json
|
|
37
|
+
insight-cli skill insight-die --json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The catalog describes the adapters and their packaged skills before any runtime is downloaded.
|
|
41
|
+
Use each tool's `status` to check the selected profile, then follow its skill and generated help.
|
|
42
|
+
The toolbox includes Ghidra, ILSpy, 7-Zip, LLVM utilities, DiE, LLDB, Frida, WinDbg, strace and .NET dump/stack/trace; platform
|
|
43
|
+
and capability limits are explicit per tool. A partial classification or a failed native process
|
|
44
|
+
is not a complete finding. Preserve useful output in ordinary project files and checkpoint it
|
|
45
|
+
with `artifacts save` when useful. Existing project RE instructions retain precedence.
|
|
46
|
+
|
|
23
47
|
## Start
|
|
24
48
|
|
|
25
49
|
```sh
|
|
26
|
-
insight-cli profile create local
|
|
50
|
+
insight-cli profile create local
|
|
27
51
|
insight-cli --profile local permissions grant Update
|
|
52
|
+
insight-cli --profile local ghidra install
|
|
53
|
+
insight-cli --profile local ghidra status
|
|
28
54
|
insight-cli --profile local ghidra open ./client.exe --session new --json
|
|
29
55
|
```
|
|
30
56
|
|
|
@@ -53,3 +79,8 @@ and `insight-cli skill insight-re` to locate packaged instructions and reference
|
|
|
53
79
|
|
|
54
80
|
Full documentation and verification: [GitHub](https://github.com/iXab3r/insight-cli).
|
|
55
81
|
License: MIT. The bundled GhidraMCP bridge has its own Apache-2.0 license and notice.
|
|
82
|
+
|
|
83
|
+
Runtime management, local archives and external paths: [managed runtime](references/managed-runtime.md).
|
|
84
|
+
The host debugger and OS permissions are checked separately by `ghidra doctor`.
|
|
85
|
+
|
|
86
|
+
Static .NET commands and ordinary output files: [ILSpy](references/ilspy.md).
|
package/SKILL.md
CHANGED
|
@@ -1,55 +1,42 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: insight-cli
|
|
3
|
-
description:
|
|
3
|
+
description: Choose and prepare reverse-engineering capabilities from the insight-cli toolbox for binary, managed-code and runtime investigations. Use to discover the appropriate tool or its packaged skill before installing native runtimes.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# insight-cli 0.1
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
their external effects do not participate in program merge.
|
|
44
|
-
|
|
45
|
-
For owned GUI execution, CPU state, breakpoints and retained traces, read
|
|
46
|
-
[debugger](references/debugger.md). Execution side effects remain separate from program publication.
|
|
47
|
-
|
|
48
|
-
For explicit external documentation exchange and retained submission outcomes, read
|
|
49
|
-
[archive](references/archive.md).
|
|
50
|
-
|
|
51
|
-
For selected native SDK extensions (VT, DB differences, byte/assembly edits, formats, GDT,
|
|
52
|
-
FID/BSim, namespaces and typed IR), read [native workflows](references/native-workflows.md).
|
|
53
|
-
|
|
54
|
-
For managed SDK extension modules, actual language/analyzer/plugin discovery and opt-in
|
|
55
|
-
automatic synchronization, read [extensions and sync](references/extensions-and-sync.md).
|
|
6
|
+
# insight-cli 0.2.1
|
|
7
|
+
|
|
8
|
+
If local help/status reports AppData or IPC access denied, retry that **read-only probe**
|
|
9
|
+
with the agent host's normal permission escalation, then use that route for later authorized
|
|
10
|
+
CLI calls too. An explicit **no command was sent** denial is known undispatched and can be
|
|
11
|
+
retried through that route. Keep HOME, profile and owner state; see
|
|
12
|
+
[host execution permissions](references/agent-execution.md). A lost mutation reply needs
|
|
13
|
+
request/status recovery, never blind retry.
|
|
14
|
+
|
|
15
|
+
Read the project's RE instructions and existing findings first. They own tool choices,
|
|
16
|
+
evidence layout, formats and source of truth. These skills fill the remaining gaps.
|
|
17
|
+
|
|
18
|
+
1. Run `insight-cli tools list --json` to discover the capabilities shipped in this version.
|
|
19
|
+
The catalog works before profile configuration, downloads or IPC startup. A downloaded
|
|
20
|
+
runtime is not needed to discover what a tool does.
|
|
21
|
+
2. Use `insight-cli tools show <tool> --json` for tasks, supported inputs/platforms,
|
|
22
|
+
dependencies and its skill path. Read that skill before preparing or using the tool.
|
|
23
|
+
3. Select a profile for execution. Run the selected application's `status` and generated
|
|
24
|
+
`--help`. `install` prepares its private runtime; archives/offline and external paths
|
|
25
|
+
are tool-specific and described in its skill. Update permission is required for tool
|
|
26
|
+
preparation/execution and saved changes: `insight-cli permissions grant Update`.
|
|
27
|
+
4. Answer the question with focused queries and ordinary project files. Follow results to
|
|
28
|
+
useful detail; a large raw dump is not an interpretation. External tools remain welcome.
|
|
29
|
+
5. Preserve completed files with `insight-cli artifacts save <path> --json` when a retained
|
|
30
|
+
checkpoint helps. For several agents sharing Ghidra analysis, use separate sessions,
|
|
31
|
+
then explicit merge/refresh as described by its skill.
|
|
32
|
+
|
|
33
|
+
`insight-cli skill` locates this entry point. `skill insight-re` gives investigation and
|
|
34
|
+
multi-agent guidance; `skill insight-ghidra`, `skill insight-ilspy` and
|
|
35
|
+
`skill insight-artifacts` locate the relevant instructions. Skills ship with the CLI;
|
|
36
|
+
installing npm binaries does not register them in an agent host. See
|
|
37
|
+
[agent connection](references/agent-setup.md) for current setup and access requirements.
|
|
38
|
+
|
|
39
|
+
Use generated help as the syntax authority. Catalog metadata describes shipped capabilities;
|
|
40
|
+
profile runtime readiness comes from the selected tool's `status`. Unavailable profile/IPC
|
|
41
|
+
access means execution readiness is unknown. Preserve work and diagnose access before trying
|
|
42
|
+
again; stopping a shared owner does not grant a denied agent access to it.
|
|
@@ -12,7 +12,7 @@ export function administrationResult(operation, p, raw) {
|
|
|
12
12
|
const value = object(raw);
|
|
13
13
|
if (JSON.stringify(value).length > 1048576)
|
|
14
14
|
fail('limit', 'Administration result exceeds one MiB.');
|
|
15
|
-
if (['status', 'connect', 'disconnect'].includes(operation)) {
|
|
15
|
+
if (['status', 'connect', 'disconnect', 'stop'].includes(operation)) {
|
|
16
16
|
if (typeof value.connected !== 'boolean' || !['local', 'external'].includes(String(value.mode)))
|
|
17
17
|
fail('partial', 'Server status is incomplete.');
|
|
18
18
|
if (value.connected && typeof value.repository !== 'string')
|
|
@@ -11,4 +11,4 @@ export declare class Administration {
|
|
|
11
11
|
read(operation: string, parameters: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
12
12
|
change(operation: string, parameters: Record<string, unknown>, callerId?: string): Promise<unknown>;
|
|
13
13
|
}
|
|
14
|
-
export declare function administrationCommands(service: (context: CommandContext) => Administration): CommandDefinition[];
|
|
14
|
+
export declare function administrationCommands(service: (context: CommandContext) => Administration, unconfiguredStatus?: (context: CommandContext) => Promise<Record<string, unknown> | undefined>): CommandDefinition[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { command, Permission } from '@eyeauras/cli-factory';
|
|
2
2
|
import { fail, id, text } from './model.js';
|
|
3
3
|
import { option, parsed, key } from './arguments.js';
|
|
4
|
+
import { runtimeProcesses } from './runtime-manager.js';
|
|
4
5
|
import { administrationResult } from './administration-results.js';
|
|
5
6
|
const repository = (value) => { const name = text(value, 128); if (name !== name.trim() || /[\\/\0]/.test(name) || name.startsWith('.'))
|
|
6
7
|
fail('invalid', 'Repository name must be a single bounded name.'); return name; };
|
|
@@ -67,6 +68,8 @@ export class Administration {
|
|
|
67
68
|
const repo = { name: 'repository', type: 'string', required: true }, path = { name: 'path', type: 'string', required: false, default: '/' };
|
|
68
69
|
const leaves = [
|
|
69
70
|
{ names: ['status'], operation: 'status', gate: Permission.ReadOnly, params: [] },
|
|
71
|
+
{ names: ['start'], operation: 'connect', gate: Permission.Update, params: [] },
|
|
72
|
+
{ names: ['stop'], operation: 'stop', gate: Permission.Update, params: [] },
|
|
70
73
|
{ names: ['connect'], operation: 'connect', gate: Permission.Update, params: [] },
|
|
71
74
|
{ names: ['disconnect'], operation: 'disconnect', gate: Permission.Update, params: [] },
|
|
72
75
|
{ names: ['repositories', 'list'], operation: 'repositories', gate: Permission.ReadOnly, params: [] },
|
|
@@ -81,11 +84,22 @@ const leaves = [
|
|
|
81
84
|
{ names: ['admin', 'terminate-checkout'], operation: 'terminate_checkout', gate: 'Destructive', params: [repo, { ...path, required: true, default: undefined }, { name: 'checkout_id', type: 'string', required: false }] },
|
|
82
85
|
{ names: ['admin', 'terminate-all-checkouts'], operation: 'terminate_all_checkouts', gate: 'Destructive', params: [repo, path] },
|
|
83
86
|
];
|
|
84
|
-
export function administrationCommands(service) {
|
|
87
|
+
export function administrationCommands(service, unconfiguredStatus) {
|
|
85
88
|
const children = [];
|
|
86
89
|
for (const leaf of leaves) {
|
|
87
90
|
const changing = leaf.gate !== Permission.ReadOnly;
|
|
88
|
-
const definition = command(leaf.names.at(-1), 'Operate on the configured server and explicit repository', ({ options: o }, c) => {
|
|
91
|
+
const definition = command(leaf.names.at(-1), 'Operate on the configured server and explicit repository', async ({ options: o }, c) => {
|
|
92
|
+
if (leaf.operation === 'stop') {
|
|
93
|
+
if (c.profile.values.server)
|
|
94
|
+
fail('authorization', 'External server lifecycle is owned by its operator. Use server disconnect.');
|
|
95
|
+
if ((await runtimeProcesses(c.appArguments.AppDataDirectory)).some(p => p.kind !== 'server'))
|
|
96
|
+
fail('busy', 'Close active Ghidra contexts before stopping their server.');
|
|
97
|
+
}
|
|
98
|
+
if (leaf.operation === 'status' && unconfiguredStatus) {
|
|
99
|
+
const passive = await unconfiguredStatus(c);
|
|
100
|
+
if (passive)
|
|
101
|
+
return passive;
|
|
102
|
+
}
|
|
89
103
|
const parameters = {};
|
|
90
104
|
for (const p of leaf.params) {
|
|
91
105
|
const value = o[key(p.name)];
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { command, Permission, CliError } from '@eyeauras/cli-factory';
|
|
2
|
+
import { join, resolve, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { mkdir, writeFile, copyFile, readFile } from 'node:fs/promises';
|
|
5
|
+
import { constants } from 'node:fs';
|
|
6
|
+
import { release } from 'node:os';
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { runTool } from './tool-runtime/run.js';
|
|
9
|
+
import { atomicWrite } from './tool-runtime/store.js';
|
|
10
|
+
import { fileSha256 } from './tool-runtime/archives.js';
|
|
11
|
+
import { fail, text, id } from './model.js';
|
|
12
|
+
import { number } from './research.js';
|
|
13
|
+
const helper = fileURLToPath(new URL('../../runtime/native/binary/insight-binary-darwin-arm64', import.meta.url));
|
|
14
|
+
export function binaryCommands(workspace) {
|
|
15
|
+
const run = (mode) => command(mode + ' [input]', mode === 'query' ? 'Inspect bounded PE, ELF or thin Mach-O metadata without executing the input' : 'Change one expected PE subsystem field in a new copy and independently read it back', async ({ args, options: o }, c) => {
|
|
16
|
+
if (process.platform !== 'darwin' || process.arch !== 'arm64' || Number(release().split('.')[0]) < 23)
|
|
17
|
+
fail('unsupported', 'The packaged LIEF facade is currently verified on macOS14+ ARM64; input formats are PE, ELF and thin Mach-O.');
|
|
18
|
+
if (Boolean(args.input) === Boolean(o.target))
|
|
19
|
+
fail('invalid', 'Supply one binary input or --target.');
|
|
20
|
+
const view = mode === 'query' ? text(o.view ?? 'overview', 16) : undefined;
|
|
21
|
+
if (view && !['overview', 'sections', 'libraries', 'imports', 'exports'].includes(view))
|
|
22
|
+
fail('invalid', 'Use overview, sections, libraries, imports or exports.');
|
|
23
|
+
const limit = number(o.limit ?? 50, 500, 1), offset = number(o.offset ?? 0, 1000000), w = workspace(c), target = args.input ? await w.importTarget(resolve(c.cwd, text(args.input, 4096))) : w.target(id(o.target));
|
|
24
|
+
if (target.input.size > 64 * 1024 ** 2)
|
|
25
|
+
fail('limit', 'Structured binary input exceeds 64 MiB.');
|
|
26
|
+
const input = await w.artifacts.verify(target.input);
|
|
27
|
+
const directory = join(c.appArguments.AppDataDirectory, 'runtime/binary/queries', randomUUID()), plan = join(directory, 'plan.json'), edited = join(directory, 'edited.exe');
|
|
28
|
+
let edit;
|
|
29
|
+
if (mode === 'edit-subsystem') {
|
|
30
|
+
if (!o.output)
|
|
31
|
+
fail('invalid', 'Copy-only editing requires --output FILE.');
|
|
32
|
+
const values = { gui: 2, console: 3 }, expected = values[text(o.expectSubsystem, 16)], value = values[text(o.subsystem, 16)];
|
|
33
|
+
if (!expected || !value || expected === value)
|
|
34
|
+
fail('invalid', 'Choose a different gui/console subsystem and an explicit --expect-subsystem.');
|
|
35
|
+
edit = { expectedSubsystem: expected, subsystem: value, output: edited };
|
|
36
|
+
}
|
|
37
|
+
await atomicWrite(plan, { schema: 1, mode, input, view, filter: o.filter === undefined ? undefined : text(o.filter, 4096), limit, offset, ...edit });
|
|
38
|
+
const result = await runTool(c, { tool: 'binary', role: mode, executable: helper, arguments: [plan], timeoutMs: 60000, maxOutputBytes: 8 * 1024 ** 2, nativeDeadline: true, target: target.id, metadata: { view, helperSha256: await fileSha256(helper) } });
|
|
39
|
+
let observation;
|
|
40
|
+
try {
|
|
41
|
+
observation = JSON.parse(result.stdout);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new CliError('Binary parser did not return complete bounded JSON.', { code: 'tool.partial', result: { process: result.process, diagnostics: result.diagnostics } });
|
|
45
|
+
}
|
|
46
|
+
if (!['completed', 'partial'].includes(observation?.state) || typeof observation.complete !== 'boolean')
|
|
47
|
+
fail('partial', 'Binary query receipt was not verified.', { process: result.process, diagnostics: result.diagnostics });
|
|
48
|
+
if (await fileSha256(input) !== target.binarySha256)
|
|
49
|
+
fail('binding', 'Immutable binary changed during inspection.');
|
|
50
|
+
const warnings = result.stderr.trim(), value = { ...observation, ...(warnings ? { state: 'partial', complete: false, reason: 'native_parser_diagnostics', warnings: warnings.slice(0, 4096), warningsTruncated: warnings.length > 4096 } : {}), target: target.id, inputSha256: target.binarySha256, process: result.process, elapsedMs: result.elapsedMs, diagnostics: result.diagnostics };
|
|
51
|
+
if (mode === 'edit-subsystem') {
|
|
52
|
+
if (!value.complete)
|
|
53
|
+
fail('partial', 'Native parser diagnostics prevent accepting the copied edit.', value);
|
|
54
|
+
const before = await readFile(input), after = await readFile(edited), at = Number(BigInt(observation.fieldOffset));
|
|
55
|
+
if (after.length !== before.length || !Number.isSafeInteger(at) || at < 0 || at + 2 > before.length)
|
|
56
|
+
fail('binding', 'Copied PE edit did not retain its field bounds.');
|
|
57
|
+
for (let n = 0; n < before.length; n++)
|
|
58
|
+
if (n !== at && n !== at + 1 && before[n] !== after[n])
|
|
59
|
+
fail('binding', 'Copied PE edit changed bytes outside the declared field.');
|
|
60
|
+
const output = resolve(c.cwd, text(o.output, 4096));
|
|
61
|
+
await mkdir(dirname(output), { recursive: true, mode: 0o700 });
|
|
62
|
+
await copyFile(edited, output, constants.COPYFILE_EXCL);
|
|
63
|
+
return { ...value, output, outputSha256: await fileSha256(output), originalPreserved: true };
|
|
64
|
+
}
|
|
65
|
+
if (o.output) {
|
|
66
|
+
const output = resolve(c.cwd, text(o.output, 4096)), content = JSON.stringify(value, null, 2) + '\n';
|
|
67
|
+
await mkdir(dirname(output), { recursive: true, mode: 0o700 });
|
|
68
|
+
await writeFile(output, content, { flag: 'wx', mode: 0o600 });
|
|
69
|
+
return { state: value.state, complete: value.complete, reason: value.reason, target: target.id, output, bytes: Buffer.byteLength(content), process: result.process, diagnostics: result.diagnostics };
|
|
70
|
+
}
|
|
71
|
+
return value;
|
|
72
|
+
}, { permission: Permission.Update, options: [{ flags: '--target <id>', description: 'Reuse immutable input bytes' }, { flags: '--output <file>', description: mode === 'query' ? 'Save this bounded page to a new JSON file' : 'Required new executable copy; never overwrite an existing file' }, ...(mode === 'query' ? [{ flags: '--view <kind>', description: 'overview, sections, libraries, imports or exports', defaultValue: 'overview' }, { flags: '--filter <text>', description: 'Literal metadata name substring before pagination' }, { flags: '--limit <count>', description: 'Return 1–500 rows', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip matching rows', defaultValue: 0 }] : [{ flags: '--expect-subsystem <kind>', description: 'Required current PE subsystem: gui or console', required: true }, { flags: '--subsystem <kind>', description: 'Required different PE subsystem: gui or console', required: true }])] });
|
|
73
|
+
return [command('binary', 'Structured binary metadata and guarded copy-only edits', [run('query'), run('edit-subsystem')])];
|
|
74
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { command, Permission, CliError } from '@eyeauras/cli-factory';
|
|
2
|
+
import { join, resolve, dirname, basename, sep } from 'node:path';
|
|
3
|
+
import { mkdir, writeFile, copyFile, chmod, open, realpath, lstat } from 'node:fs/promises';
|
|
4
|
+
import { constants } from 'node:fs';
|
|
5
|
+
import { release } from 'node:os';
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { runTool } from './tool-runtime/run.js';
|
|
8
|
+
import { atomicWrite, readJson } from './tool-runtime/store.js';
|
|
9
|
+
import { listProcesses } from './tool-runtime/supervisor.js';
|
|
10
|
+
import { fileSha256 } from './tool-runtime/archives.js';
|
|
11
|
+
import { fail, text, id } from './model.js';
|
|
12
|
+
import { number } from './research.js';
|
|
13
|
+
const sha = (b) => createHash('sha256').update(b).digest('hex');
|
|
14
|
+
const list = (v) => v === undefined ? [] : (Array.isArray(v) ? v : [v]).map(s => text(s, 4096));
|
|
15
|
+
const root = (c, request) => { if (!/^a_[a-f0-9-]{36}$/.test(request))
|
|
16
|
+
fail('invalid', 'Select a capture request returned by capture run.'); return join(c.appArguments.AppDataDirectory, 'runtime/capture', request); };
|
|
17
|
+
function relativeFile(value) { const name = text(value, 1024); if (name.includes('\\') || name.startsWith('/') || name.split('/').some(p => !p || p === '.' || p === '..') || name.toLowerCase() === 'subject')
|
|
18
|
+
fail('invalid', 'Watch paths must be ordinary relative files inside the owned working directory.'); return name; }
|
|
19
|
+
async function boundedFile(path, max = 16 * 1024 ** 2) {
|
|
20
|
+
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
21
|
+
try {
|
|
22
|
+
const before = await handle.stat();
|
|
23
|
+
if (!before.isFile() || before.size > max)
|
|
24
|
+
fail('limit', 'Selected file must be regular and within its byte bound.');
|
|
25
|
+
const chunks = [];
|
|
26
|
+
let bytes = 0;
|
|
27
|
+
for await (const chunk of handle.createReadStream({ autoClose: false })) {
|
|
28
|
+
bytes += chunk.length;
|
|
29
|
+
if (bytes > max)
|
|
30
|
+
fail('limit', 'Selected file grew beyond its capture bound.');
|
|
31
|
+
chunks.push(chunk);
|
|
32
|
+
}
|
|
33
|
+
const after = await handle.stat();
|
|
34
|
+
if (before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.ino !== after.ino)
|
|
35
|
+
fail('binding', 'Selected file changed while being read.');
|
|
36
|
+
return Buffer.concat(chunks);
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
await handle.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function snapshot(directory, name) {
|
|
43
|
+
const file = join(directory, name);
|
|
44
|
+
try {
|
|
45
|
+
const parent = await realpath(dirname(file)), base = await realpath(directory);
|
|
46
|
+
if (parent !== base && !parent.startsWith(base + sep))
|
|
47
|
+
return { path: name, state: 'unavailable', reason: 'parent_outside_owned_directory' };
|
|
48
|
+
const info = await lstat(file);
|
|
49
|
+
if (!info.isFile() || info.isSymbolicLink())
|
|
50
|
+
return { path: name, state: 'unavailable', reason: 'not_regular_file' };
|
|
51
|
+
const bytes = await boundedFile(file);
|
|
52
|
+
return { path: name, state: 'present', bytes: bytes.length, sha256: sha(bytes) };
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error.code === 'ENOENT')
|
|
56
|
+
return { path: name, state: 'absent' };
|
|
57
|
+
return { path: name, state: 'unavailable', reason: error.code ?? 'unreadable' };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function pageStream(value, offset, limit) { if (!value)
|
|
61
|
+
return { available: false }; const all = Buffer.from(value.base64, 'base64'), bytes = all.subarray(offset, offset + limit); return { available: true, totalBytes: value.bytes, sha256: value.sha256, offset, limit, base64: bytes.toString('base64'), text: bytes.toString('utf8'), textEncoding: 'UTF-8 preview with replacement; base64 preserves exact selected bytes', truncated: offset + limit < all.length }; }
|
|
62
|
+
function overview(receipt) { const { stdout, stderr, files, ...rest } = receipt; return { ...rest, stdout: pageStream(stdout, 0, 256), stderr: pageStream(stderr, 0, 256), declaredFiles: files.length, fileChanges: files.filter(f => f.change !== 'unchanged').map(f => ({ path: f.path, change: f.change })) }; }
|
|
63
|
+
async function exportReceipt(c, value, option) { const output = resolve(c.cwd, text(option, 4096)), content = JSON.stringify(value, null, 2) + '\n'; await mkdir(dirname(output), { recursive: true, mode: 0o700 }); await writeFile(output, content, { flag: 'wx', mode: 0o600 }); return output; }
|
|
64
|
+
async function receiptFor(c, w, request) { const stored = w.administration(request); if (stored.operation !== 'capture.run')
|
|
65
|
+
fail('invalid', 'Request is not an owned process capture.'); const file = join(root(c, request), 'capture.json'), receipt = await readJson(file); if (receipt && stored.state === 'applied') {
|
|
66
|
+
const result = stored.result;
|
|
67
|
+
if (result?.receiptSha256 !== await fileSha256(file))
|
|
68
|
+
fail('binding', 'Capture receipt differs from its durable outcome.');
|
|
69
|
+
validateReport(receipt);
|
|
70
|
+
if (receipt.request !== request)
|
|
71
|
+
fail('binding', 'Capture receipt has a different request identity.');
|
|
72
|
+
return receipt;
|
|
73
|
+
} return { state: stored.state === 'accepted' ? 'prepared' : 'unknown', complete: false, request, intent: stored.intent, processes: (await listProcesses(c.appArguments.AppDataDirectory, { tool: 'capture' })).filter(p => p.metadata?.request === request), directory: root(c, request), workingDirectory: join(root(c, request), 'working'), scope: 'No completed capture receipt. Inspect retained process/input/files explicitly; never rerun this request to manufacture a result.' }; }
|
|
74
|
+
function validateReport(value) {
|
|
75
|
+
const hash = (v) => typeof v === 'string' && /^[a-f0-9]{64}$/.test(v);
|
|
76
|
+
if (value?.schema !== 1 || value.kind !== 'insight-process-capture' || typeof value.complete !== 'boolean' || value.state !== (value.complete ? 'completed' : 'partial') || !hash(value.inputSha256) || !Array.isArray(value.files) || value.files.length > 32 || !value.execution || !Array.isArray(value.arguments) || value.arguments.length > 64 || value.arguments.some(a => typeof a !== 'string' || a.length > 4096) || !Array.isArray(value.inputs) || value.inputs.length > 32)
|
|
77
|
+
fail('invalid', 'Select a structured insight process capture report.');
|
|
78
|
+
if (value.execution.exitCode !== null && (!Number.isInteger(value.execution.exitCode) || value.execution.exitCode < 0 || value.execution.exitCode > 255))
|
|
79
|
+
fail('invalid', 'Invalid captured exit code.');
|
|
80
|
+
let bytes = 0;
|
|
81
|
+
for (const stream of [value.stdout, value.stderr])
|
|
82
|
+
if (stream) {
|
|
83
|
+
if (!hash(stream.sha256) || typeof stream.base64 !== 'string')
|
|
84
|
+
fail('invalid', 'Malformed capture byte stream.');
|
|
85
|
+
const raw = Buffer.from(stream.base64, 'base64');
|
|
86
|
+
if (raw.toString('base64') !== stream.base64 || raw.length !== stream.bytes || sha(raw) !== stream.sha256 || (bytes += raw.length) > 4 * 1024 ** 2)
|
|
87
|
+
fail('binding', 'Capture byte stream differs from its bounds/hash.');
|
|
88
|
+
}
|
|
89
|
+
if (value.complete && (!value.stdout || !value.stderr || value.execution.exitCode === null || value.execution.signal !== null))
|
|
90
|
+
fail('invalid', 'A complete capture requires known terminal output and exit.');
|
|
91
|
+
const seen = new Set();
|
|
92
|
+
for (const file of value.files) {
|
|
93
|
+
const name = relativeFile(file.path);
|
|
94
|
+
if (seen.has(name))
|
|
95
|
+
fail('invalid', 'Duplicate declared capture path.');
|
|
96
|
+
seen.add(name);
|
|
97
|
+
for (const observed of [file.before, file.after])
|
|
98
|
+
if (!observed || observed.path !== name || !['present', 'absent', 'unavailable'].includes(observed.state) || observed.state === 'present' && (!hash(observed.sha256) || !Number.isSafeInteger(observed.bytes) || observed.bytes < 0 || observed.bytes > 16 * 1024 ** 2))
|
|
99
|
+
fail('invalid', 'Malformed declared file observation.');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function captureCommands(workspace) {
|
|
103
|
+
const run = command('run [input]', 'Capture one explicitly selected owned native execution and declared file snapshots', async ({ args, options: o }, c) => {
|
|
104
|
+
if (process.platform !== 'darwin' || process.arch !== 'arm64' || Number(release().split('.')[0]) < 23)
|
|
105
|
+
fail('unsupported', 'Process capture is verified on macOS14+ ARM64 thin native executables.');
|
|
106
|
+
if (Boolean(args.input) === Boolean(o.target))
|
|
107
|
+
fail('invalid', 'Supply one native program or --target.');
|
|
108
|
+
const w = workspace(c), target = args.input ? await w.importTarget(resolve(c.cwd, text(args.input, 4096))) : w.target(id(o.target)), input = await w.artifacts.verify(target.input);
|
|
109
|
+
if (target.input.size > 64 * 1024 ** 2)
|
|
110
|
+
fail('limit', 'Owned executable exceeds 64 MiB.');
|
|
111
|
+
const header = (await boundedFile(input, 64 * 1024 ** 2)).subarray(0, 32);
|
|
112
|
+
if (header.length < 32 || header.subarray(0, 4).toString('hex') !== 'cffaedfe' || header.readUInt32LE(4) !== 0x0100000c || header.readUInt32LE(12) !== 2)
|
|
113
|
+
fail('unsupported', 'Select a thin ARM64 Mach-O executable, not a PE/ELF, script, library or universal container.');
|
|
114
|
+
const argv = list(o.arg), selected = list(o.inputFile), watched = [...new Set(list(o.watch).map(relativeFile))];
|
|
115
|
+
if (argv.length > 64 || selected.length > 32 || watched.length > 32)
|
|
116
|
+
fail('limit', 'Capture permits 64 literal arguments, 32 selected input files and 32 watch paths.');
|
|
117
|
+
const timeoutMs = number(o.timeoutSeconds ?? 10, 600, 1) * 1000, files = [];
|
|
118
|
+
let total = 0;
|
|
119
|
+
for (const option of selected) {
|
|
120
|
+
const path = resolve(c.cwd, option), name = basename(path);
|
|
121
|
+
if (name.toLowerCase() === 'subject' || files.some(f => f.name.normalize('NFD').toLowerCase() === name.normalize('NFD').toLowerCase()) || !/^[^/\\\0]+$/.test(name))
|
|
122
|
+
fail('invalid', 'Selected input basenames must be ordinary and unique.');
|
|
123
|
+
const data = await boundedFile(path);
|
|
124
|
+
if ((total += data.length) > 64 * 1024 ** 2)
|
|
125
|
+
fail('limit', 'Selected input files exceed 64 MiB.');
|
|
126
|
+
files.push({ name, sha256: sha(data), bytes: data.length, data });
|
|
127
|
+
}
|
|
128
|
+
const stdin = o.stdinFile ? await boundedFile(resolve(c.cwd, text(o.stdinFile, 4096)), 1024 ** 2) : Buffer.alloc(0);
|
|
129
|
+
if (o.output && !(o.requestId && w.administrationByCaller(id(o.requestId))))
|
|
130
|
+
try {
|
|
131
|
+
await lstat(resolve(c.cwd, text(o.output, 4096)));
|
|
132
|
+
fail('invalid', 'Capture output already exists.');
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (error.code !== 'ENOENT')
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
const intent = { target: target.id, inputSha256: target.binarySha256, arguments: argv, inputs: files.map(({ data, ...f }) => f), stdin: { sha256: sha(stdin), bytes: stdin.length }, watch: watched, timeoutMs, output: o.output ? resolve(c.cwd, text(o.output, 4096)) : undefined };
|
|
139
|
+
const reservation = w.reserveAdministration('capture.run', intent, o.requestId === undefined ? undefined : id(o.requestId)), request = reservation.request.id;
|
|
140
|
+
if (reservation.replay) {
|
|
141
|
+
const previous = await receiptFor(c, w, request);
|
|
142
|
+
if (reservation.request.state === 'applied' && 'kind' in previous) {
|
|
143
|
+
if (!previous.complete)
|
|
144
|
+
throw new CliError('Prior capture remains partial; no execution was repeated.', { code: 'tool.capture.partial', result: overview(previous) });
|
|
145
|
+
return { ...overview(previous), replayed: true };
|
|
146
|
+
}
|
|
147
|
+
throw new CliError('Capture request already exists without a verified complete outcome; no execution was repeated.', { code: 'tool.capture.unknown', result: previous });
|
|
148
|
+
}
|
|
149
|
+
const directory = root(c, request), working = join(directory, 'working'), subject = join(working, 'subject');
|
|
150
|
+
await mkdir(working, { recursive: true, mode: 0o700 });
|
|
151
|
+
await copyFile(input, subject, constants.COPYFILE_EXCL);
|
|
152
|
+
await chmod(subject, 0o700);
|
|
153
|
+
if (await fileSha256(subject) !== target.binarySha256)
|
|
154
|
+
fail('binding', 'Owned executable differs from captured input.');
|
|
155
|
+
for (const f of files)
|
|
156
|
+
await writeFile(join(working, f.name), f.data, { flag: 'wx', mode: 0o600 });
|
|
157
|
+
const before = await Promise.all(watched.map(name => snapshot(working, name)));
|
|
158
|
+
await atomicWrite(join(directory, 'intent.json'), { request, ...intent });
|
|
159
|
+
w.administrationState(request, 'running', { directory });
|
|
160
|
+
let result, failure;
|
|
161
|
+
try {
|
|
162
|
+
result = await runTool(c, { tool: 'capture', role: 'run', executable: subject, arguments: argv, cwd: working, input: stdin, timeoutMs, maxOutputBytes: 4 * 1024 ** 2, retainRawOutput: true, nativeDeadline: true, acceptedCodes: Array.from({ length: 127 }, (_, n) => n), target: target.id, metadata: { request, working, scope: 'Owned program copy; selected input copies and declared file snapshots; no shell or OS sandbox' } });
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
failure = error;
|
|
166
|
+
if (error instanceof CliError && error.result && typeof error.result === 'object' && 'stdout' in error.result)
|
|
167
|
+
result = error.result;
|
|
168
|
+
}
|
|
169
|
+
const after = await Promise.all(watched.map(name => snapshot(working, name))), unavailable = [...before, ...after].some(f => f.state === 'unavailable');
|
|
170
|
+
const stream = async (file) => { if (!file)
|
|
171
|
+
return; const b = await boundedFile(file, 4 * 1024 ** 2); return { bytes: b.length, sha256: sha(b), base64: b.toString('base64') }; };
|
|
172
|
+
const value = { schema: 1, kind: 'insight-process-capture', request, state: failure || unavailable ? 'partial' : 'completed', complete: !failure && !unavailable, ...(failure ? { reason: failure instanceof CliError ? failure.code : 'capture_failed' } : unavailable ? { reason: 'declared_file_unavailable' } : {}), target: target.id, inputSha256: target.binarySha256, timeoutMs, arguments: argv, inputs: intent.inputs, stdin: intent.stdin, stdout: await stream(result?.rawStdout), stderr: await stream(result?.rawStderr), execution: { process: result?.process, exitCode: result?.exitCode ?? null, signal: result?.signal ?? null, elapsedMs: result?.elapsedMs, diagnostics: result?.diagnostics }, files: watched.map((path, n) => { const a = before[n], b = after[n]; return { path, before: a, after: b, change: a.state === 'unavailable' || b.state === 'unavailable' ? 'unknown' : a.state === b.state && (a.state === 'absent' || a.sha256 === b.sha256) ? 'unchanged' : a.state === 'absent' ? 'created' : b.state === 'absent' ? 'deleted' : 'changed' }; }), scope: 'One owned program copy with literal argv, exact bounded stdout/stderr bytes and selected file snapshots. This is not an OS sandbox, a trace of all filesystem/network effects or proof of causality. Native deadline assumes the subject does not deliberately replace the inherited alarm. Known nonzero subject exits are captured outcomes; interrupted/overflow/unknown capture stays partial.' };
|
|
173
|
+
if (!value.stdout || !value.stderr) {
|
|
174
|
+
value.complete = false;
|
|
175
|
+
value.state = 'partial';
|
|
176
|
+
value.reason ??= 'raw_output_unavailable';
|
|
177
|
+
}
|
|
178
|
+
const path = join(directory, 'capture.json');
|
|
179
|
+
await atomicWrite(path, value);
|
|
180
|
+
w.administrationState(request, 'applied', { receipt: path, receiptSha256: await fileSha256(path), complete: value.complete });
|
|
181
|
+
const output = o.output ? await exportReceipt(c, value, o.output) : undefined;
|
|
182
|
+
if (!value.complete)
|
|
183
|
+
throw new CliError('Capture is partial; retained output/files are available and execution was not replayed.', { code: 'tool.capture.partial', result: { ...overview(value), directory, ...(output ? { output } : {}) } });
|
|
184
|
+
return { ...overview(value), directory, ...(output ? { output } : {}) };
|
|
185
|
+
}, { permission: Permission.Update, options: [{ flags: '--target <id>', description: 'Reuse immutable native program bytes' }, { flags: '--arg <text...>', description: 'Literal subject arguments; no shell string or expansion' }, { flags: '--input-file <file...>', description: 'Copy selected regular files by unique basename into owned cwd' }, { flags: '--stdin-file <file>', description: 'Optional bounded input byte stream (up to 1 MiB)' }, { flags: '--watch <path...>', description: 'Declared relative regular files to snapshot before and after execution' }, { flags: '--timeout-seconds <seconds>', description: 'Owned execution deadline (1–600)', defaultValue: 10 }, { flags: '--output <file>', description: 'Save a new portable bounded JSON capture, including exact output base64' }, { flags: '--request-id <id>', description: 'Retrieve this exact capture intent without executing it again' }] });
|
|
186
|
+
const show = command('show <request>', 'Inspect retained capture bytes or an unresolved intent without rerunning a program', async ({ args, options: o }, c) => { const request = text(args.request, 128), value = await receiptFor(c, workspace(c), request); if (!('kind' in value))
|
|
187
|
+
return value; if (o.output)
|
|
188
|
+
return { request, complete: value.complete, output: await exportReceipt(c, value, o.output) }; const view = text(o.view ?? 'overview', 16), limit = number(o.limit ?? 50, 1000, 1), offset = number(o.offset ?? 0, 8 * 1024 ** 2); if (view === 'overview')
|
|
189
|
+
return overview(value); if (view === 'stdout' || view === 'stderr')
|
|
190
|
+
return { request, state: value.state, complete: value.complete, view, ...pageStream(value[view], offset, limit) }; if (view === 'files')
|
|
191
|
+
return { request, state: value.state, complete: value.complete, items: value.files.slice(offset, offset + limit), total: value.files.length, offset, limit, truncated: offset + limit < value.files.length }; fail('invalid', 'Use overview, stdout, stderr or files.'); }, { permission: Permission.Update, options: [{ flags: '--view <kind>', description: 'overview, stdout, stderr or files', defaultValue: 'overview' }, { flags: '--limit <count>', description: '1–1000 output bytes or file rows', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip output bytes or file rows', defaultValue: 0 }, { flags: '--output <file>', description: 'Export portable retained capture to a new ordinary JSON file' }] });
|
|
192
|
+
const compare = command('compare <left> <right>', 'Compare two retained capture reports without re-executing their subjects', async ({ args, options: o }, c) => {
|
|
193
|
+
async function load(path) { const file = resolve(c.cwd, text(path, 4096)), bytes = await boundedFile(file, 8 * 1024 ** 2); let value; try {
|
|
194
|
+
value = JSON.parse(bytes.toString('utf8'));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
fail('invalid', 'Capture report must be bounded JSON.');
|
|
198
|
+
} validateReport(value); return { value, sha256: sha(bytes) }; }
|
|
199
|
+
const left = await load(args.left), right = await load(args.right), a = left.value, b = right.value, changes = [], unknown = [];
|
|
200
|
+
for (const field of ['stdout', 'stderr']) {
|
|
201
|
+
if (!a[field] || !b[field])
|
|
202
|
+
unknown.push(field);
|
|
203
|
+
else if (a[field].sha256 !== b[field].sha256)
|
|
204
|
+
changes.push({ field, left: a[field].sha256, right: b[field].sha256 });
|
|
205
|
+
}
|
|
206
|
+
if (a.execution.exitCode !== b.execution.exitCode || a.execution.signal !== b.execution.signal)
|
|
207
|
+
changes.push({ field: 'exit', left: a.execution, right: b.execution });
|
|
208
|
+
const af = new Map(a.files.map(f => [f.path, f])), bf = new Map(b.files.map(f => [f.path, f]));
|
|
209
|
+
for (const name of [...new Set([...af.keys(), ...bf.keys()])].sort()) {
|
|
210
|
+
const l = af.get(name)?.after, r = bf.get(name)?.after;
|
|
211
|
+
if (!l || !r || l.state === 'unavailable' || r.state === 'unavailable')
|
|
212
|
+
unknown.push('file:' + name);
|
|
213
|
+
else if (l.state !== r.state || l.sha256 !== r.sha256)
|
|
214
|
+
changes.push({ field: 'file:' + name, left: l, right: r });
|
|
215
|
+
}
|
|
216
|
+
const limit = number(o.limit ?? 50, 500, 1), offset = number(o.offset ?? 0, 1000000), complete = a.complete && b.complete && !unknown.length;
|
|
217
|
+
return { state: complete ? 'completed' : 'partial', complete, left: { reportSha256: left.sha256, inputSha256: a.inputSha256 }, right: { reportSha256: right.sha256, inputSha256: b.inputSha256 }, sameDeclaredIntent: JSON.stringify({ target: a.inputSha256, argv: a.arguments, inputs: a.inputs, stdin: a.stdin, watch: a.files.map(f => f.path), timeoutMs: a.timeoutMs }) === JSON.stringify({ target: b.inputSha256, argv: b.arguments, inputs: b.inputs, stdin: b.stdin, watch: b.files.map(f => f.path), timeoutMs: b.timeoutMs }), items: changes.slice(offset, offset + limit), total: changes.length, unknown, offset, limit, truncated: offset + limit < changes.length, scope: 'Literal retained field/byte comparison; no subject rerun, causal equivalence or execution-time speedup claim. Partial reports cannot prove global equality.' };
|
|
218
|
+
}, { permission: Permission.ReadOnly, options: [{ flags: '--limit <count>', description: 'Return 1–500 changed fields', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip changed fields', defaultValue: 0 }] });
|
|
219
|
+
return [command('capture', 'Own bounded native executions and compare explicitly retained observations', [run, show, compare])];
|
|
220
|
+
}
|