mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
f46cd6770c8dd05e22ead3f082acf4e214bfd8b4
2521
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4126698407 |
feat(mcp): project compact input schemas into the portable advertised dialect (#10632)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): re-emit advertised patterns in a portable regex grammar * fix(mcp): present discover_tools input through the selected profile The hot-cold catalog registered discover_tools directly with the SDK, so the default compact input profile still advertised its canonical schema, including page-size defaults clients apply on their own (#5322). Route every listed input schema, transport discovery included, through one server-owned presentation, and pass the selected presentation to the deferred server, which serves recorded tool schemas but not discovery. * fix(mcp): keep the Evidence union on described borrowed inputs borrowEvidenceInput installed its advertised projection on one schema instance. A call site's .describe() rebuilds the schema from its definition, so match_native_functions advertised left and right as unconstrained values in every input profile. Install the projection in the borrowed parser's constructor so derived schemas keep it, for both borrowed inputs and borrowed arrays. * fix(mcp): validate advertised dialect by selected profile * fix(mcp): preserve schema widening through references * feat(mcp): project compact input schemas into the portable advertised dialect One projection (advertisedDialectProjection.ts) owns the compact input advertisement: one type per node, items on every array, string literals as enums, oneOf widened to anyOf, allOf merged, tuples as element unions, exclusive bounds made inclusive, and every keyword outside the dialect dropped. Each rewrite is exact or widening; server validation is unchanged. The root description and sentences for dropped cross-field constraints move to the tool description, which Codex and Zed keep. The compact baseline falls to nullable values only (29), which the dialect cannot express without narrowing an input. The gateway shape repairs (typeArrayItemUnions, hasGatewayIncompatibleShape), the second dependentRequired-to-prose copy and the strict-gateway test denylist are removed; the dialect checker gates the inline presentation instead. * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns * fix(mcp): keep projected schemas permissive * fix(mcp): keep references valid when presentation widens their targets * fix(mcp): keep a single union branch's closure scoped to its properties * fix(mcp): keep an allOf member's tuple tail with its own positions * fix(mcp): relax references into negations and conditionals presentation may remove * test(mcp): select the borrowed Evidence contract from its family * fix(mcp): keep astral literals and dynamic references widening in every mode * fix(mcp): omit astral literals and relax untracked references when presentation widens * fix(mcp): read reference pointers by schema position, not segment spelling * fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse * fix(mcp): keep reduced schemas open when their root admits names by pattern * test(mcp): keep the reduced-schema pattern case outside the size-limited block * fix(mcp): omit patterns whose classes name astral characters * fix(mcp): decide union collapse and pointer protection from canonical branches * docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes * fix(mcp): keep prototype-named properties as own properties in the dialect projection * test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe * fix(mcp): protect references into unevaluated keywords lost evaluation removes * fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings * fix(mcp): protect references into literal siblings of relaxed draft-07 references * feat(mcp): omit output schemas from tools/list by default (#10646) * feat(mcp): omit output schemas from tools/list by default No surveyed model API reads an output schema, MCP client validators repeat REA's own result validation, and complete output schemas were about 92% of the default tools/list. REA_MCP_OUTPUT_SCHEMA_PROFILE now resolves to off through one owner (resolveMcpOutputSchemaProfile); compact and full remain selectable. structuredContent is still delivered, and the deferred server serves both off and full from the recorded catalog with the matching recorded identity. Tests and artifact verifiers that validate results against complete advertised output contracts select full explicitly. * fix(mcp): select schemas in verification workflows * fix(mcp): select complete output schemas in the Electron verifier * fix(mcp): select complete output schemas in standalone verifier probes * fix(mcp): select complete output schemas in every verifier transport * test(mcp): select full output schemas in packet and signal schema checks * fix(mcp): validate the doctor probe reply against the canonical output contract (#10655) * fix(mcp): validate the doctor probe reply against the canonical output contract * test(mcp): replay doctor probe validation under every output profile * test(mcp): accept typed-branch nullable unions in the advertised dialect (#10649) * test(mcp): select full output schemas in HTTP session workflows * fix(mcp): keep the Evidence union on described borrowed inputs (#10597) * fix(mcp): keep the Evidence union on described borrowed inputs borrowEvidenceInput installed its advertised projection on one schema instance. A call site's .describe() rebuilds the schema from its definition, so match_native_functions advertised left and right as unconstrained values in every input profile. Install the projection in the borrowed parser's constructor so derived schemas keep it, for both borrowed inputs and borrowed arrays. * test(mcp): select the borrowed Evidence contract from its family * docs(mcp): admit baseline growth only for restored contract declarations * fix(mcp): state reduced multi-type properties as typed branches, not type lists The reduced fallback derived a property's types and emitted them as a type list, which Gemini, Moonshot and Ark reject. A property whose canonical schema is anyOf string and number therefore traded a typed union for a rejected construct when the inline projection fell back. Emit one type, or anyOf typed branches, so [T, null] becomes the dialect's nullable union. |
||
|
|
da8f366596 |
fix(mcp): register fx and MCPorter where they read their configuration (#10698)
* fix(mcp): register fx and MCPorter where they read their configuration fx reads $FX_HOME/mcp.json when FX_HOME is set, and MCPorter reads MCPORTER_CONFIG exclusively or prefers an absolute XDG_CONFIG_HOME file. rea mcp add always wrote ~/.fx/mcp.json and ~/.mcporter/mcporter.json, which those clients then ignored. Resolve both from the clients' own rules, and refuse an FX_HOME fx itself refuses. * fix(mcp): detect MCPorter by its selected file and refuse FX_HOME aliases Address review findings: MCPORTER_CONFIG now also names the detection marker, so default registration includes MCPorter when only that file exists, and is resolved with path.resolve as MCPorter does. FX_HOME with . or .. segments is refused, so the private profile mode cannot reach the home folder through an alias. Override tests use the host's path rules for real temporary paths. * fix(mcp): never apply fx's private folder mode to the home folder A linked parent in FX_HOME can name the caller's home folder after the textual root and home checks pass. The private profile writer now compares the opened folder's identity with the caller's home folder and refuses before changing modes or publishing. * feat(setup): let doctor, update and uninstall see MCPorter registrations (#10702) * feat(setup): let doctor, update and uninstall see MCPorter registrations MCPorter becomes a client-table row, so a registration rea mcp add or rea setup --client mcporter wrote is inspected, refreshed and removed like other clients. MCPorter already imports setup-managed clients' registrations, so the row is applicable only through REA's own registration: setup never selects it from detection and doctor reports it only when its file holds a rea row or the caller selects it. A relative MCPORTER_CONFIG is refused because MCPorter resolves it per command directory. * fix(setup): detect MCPorter by the folder of the file it loads With an absolute XDG_CONFIG_HOME and only a legacy ~/.mcporter file, the row returned the legacy file but the absent XDG folder as its detection evidence, so default registration and setup skipped MCPorter. * fix(setup): keep an unresolved client unknown without blocking others' maintenance A client whose configuration location cannot be resolved (for example a relative MCPORTER_CONFIG) is reported as unknown, never missing or absent. Update maintenance leaves each unresolved client out of its scope and names it with its own recovery, while still maintaining the other clients; uninstall still stops, because it cannot tell whether that client's file holds REA's row. * docs(setup): restore MCPorter's release note and client-table row after rebase * fix(update): keep unknown clients in every failed maintenance plan |
||
|
|
422cff00ab |
refactor(process): give POSIX PATH search order one owner (#10891)
* refactor(process): give POSIX PATH search order one owner Program lookup, the packet-tool locator and Jadx's Java lookup each split PATH and resolved empty and relative entries themselves. They now take the candidates from posixPathCandidates in src/process/executableSearch and keep only their own probe and failure reporting. A counted architecture guard keeps new PATH splits from returning; the remaining Windows and Ghidra searches are baselined. * refactor(process): move the colon-split PATH searches onto the search owner REA's launcher-alias lookup and Ghidra's macOS Java lookup split PATH on ":" and skipped relative entries themselves; they now use posixPathCandidates with relativeEntries: "skip", and the guard counts colon splits of PATH as well. * fix(process): produce PATH candidates lazily so an unused entry cannot fail an earlier match * refactor(process): give Windows PATH/PATHEXT search order the executable search owner (#10916) * refactor(process): give Windows PATH/PATHEXT search order the executable search owner * fix(process): keep later PATH entries searchable after a stray quote or a removed working directory * fix(reverse): refuse a Windows objdump or Rizin command that PATH does not find (#10953) * fix(reverse): refuse an objdump or Rizin command Windows PATH does not find instead of launching the bare name * fix(reverse): report a Windows lookup refusal after cancellation and to capability discovery * fix(desktop): search a Windows host's PATH as Windows does when doctor looks up a program programOnPath sent every host through the POSIX PATH search, so on Windows a relative PATH entry reached absoluteCallerPath with platform linux and the Windows working directory, which resolved against itself until the stack overflowed. programOnPath now searches PATH and PATHEXT through windowsPathCandidates on a Windows host, and absoluteCallerPath refuses a non-POSIX working directory with a TypeError instead of recursing. |
||
|
|
e793fd6808 |
feat(mcp): name the next operation when a completed result overflows the response budget (#11015)
* feat(mcp): name the next operation when a completed result overflows the response budget * test(mcp): assert next_operation for every overflow recovery route |
||
|
|
b572dbaf25 | feat(setup): mark a shared enable:false registration as a manual conflict in doctor status (#11019) | ||
|
|
4aefe2daec |
fix(errors): name rea doctor only for providers it can check (#10565)
* fix(errors): name rea doctor only for providers it can check An unclassified ProviderAdapterError, an unreadable result and the final presentation fallback all told the caller to run rea doctor, although doctor checks only hopper, ghidra, ida, jadx, kuna and desktop_build. The doctor scope list moves into the domain so presentation can consult it: covered providers get `rea doctor --provider ID`, others are told plainly that the failure is unclassified and where its reason is reported. Producers whose actionable reason lived only in details.diagnostics now author it: Ghidra's committed-profile conflicts share one owner that says to reopen the target, closed analysis clients share one owner, and a jadx-reported request failure no longer points at provider readiness. The deep-analysis profile rejection names doctor only for doctor-checkable providers. Dead presentation branches for tags handled earlier are removed. * fix(errors): make provider recovery actionable * test(android): remove brittle recovery wording check * test: wait for observed child exit before cancellation * test(errors): check that doctor is not offered instead of matching recovery prose |
||
|
|
babfc87ec0 |
fix(mcp): present discover_tools input through the selected profile (#10592)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): re-emit advertised patterns in a portable regex grammar * fix(mcp): present discover_tools input through the selected profile The hot-cold catalog registered discover_tools directly with the SDK, so the default compact input profile still advertised its canonical schema, including page-size defaults clients apply on their own (#5322). Route every listed input schema, transport discovery included, through one server-owned presentation, and pass the selected presentation to the deferred server, which serves recorded tool schemas but not discovery. * fix(mcp): validate advertised dialect by selected profile * fix(mcp): preserve schema widening through references * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns * fix(mcp): keep references valid when presentation widens their targets * fix(mcp): relax references into negations and conditionals presentation may remove * fix(mcp): keep astral literals and dynamic references widening in every mode * fix(mcp): omit astral literals and relax untracked references when presentation widens * fix(mcp): read reference pointers by schema position, not segment spelling * fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse * fix(mcp): omit patterns whose classes name astral characters * fix(mcp): decide union collapse and pointer protection from canonical branches * docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes * test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe * fix(mcp): protect references into unevaluated keywords lost evaluation removes * fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings * fix(mcp): protect references into literal siblings of relaxed draft-07 references * fix(mcp): keep the Evidence union on described borrowed inputs (#10597) * fix(mcp): keep the Evidence union on described borrowed inputs borrowEvidenceInput installed its advertised projection on one schema instance. A call site's .describe() rebuilds the schema from its definition, so match_native_functions advertised left and right as unconstrained values in every input profile. Install the projection in the borrowed parser's constructor so derived schemas keep it, for both borrowed inputs and borrowed arrays. * test(mcp): select the borrowed Evidence contract from its family * docs(mcp): admit baseline growth only for restored contract declarations |
||
|
|
80755a9d16 |
fix(doctor): refuse Ghidra on Windows when REA_GHIDRA_PROJECT_PATH selects an existing project (#10981)
* fix(doctor): refuse Ghidra on Windows when REA_GHIDRA_PROJECT_PATH selects an existing project Runtime refused an existing project on Windows before admission, but doctor did not read REA_GHIDRA_PROJECT_PATH, so it reported Ghidra ready for a registration the provider then refused. The existing-project host check is now part of Ghidra's admission owner; doctor reads the setting from the client's registration and reports a failed existing_project check, and the provider projects the same refusal. An unresolved project path makes doctor's Ghidra answer unknown only on Windows, the one host it affects. * test(ghidra): read the existing-project setting through doctor's system inspection |
||
|
|
27b732e957 |
refactor(kuna): decide Kuna readiness once for doctor and runtime (#10997)
Runtime availability admitted Kuna from its settings and a runnable command, while doctor also required a passing version probe and cache inspection, so doctor could report Kuna unavailable while runtime admitted it. admitKunaCommand is now the one readiness decision: provider availability, the installation inspection and doctor's installation check all project it. Doctor reports the version probe and the cache inspection as separate health checks (version, cache) beside admission; they no longer decide availability, and runtime still does not pay for them. Setup continues to list Kuna as a ready provider only when every check passes. |
||
|
|
26520bd290 |
refactor(providers): finalize apktool and shared artifact resources through runOwned (#10653)
* refactor(providers): finalize apktool and shared artifact resources through runOwned runOwned moves to the provider layer so provider sites can use it without depending on application workflows. It gains a completed-value projection (partial) for values that are not themselves partial observations, an optional signal, and cleanupLeases that bind a close failure to the exact leases whose confirmed release resolves it. ArtifactAnalysisResources.finish is removed; TShark and sigrok finalize through runOwned with the shared release as close. Apktool's hand-written release, cancellation and lease-group composition is replaced by runOwned. A failed primary now keeps a cancellation observed during final cleanup as a secondary failure, as the documented precedence requires. A counted architecture guard refuses new hand-written completed-result abort reclassification outside runOwned. * refactor(adb): finalize runtime-root work through runOwned (#10660) * refactor(adb): finalize runtime-root work through runOwned The ADB runtime-root finalizer re-derived the precedence by hand and kept its own cancellation-with-cleanup combiner. It now runs through runOwned: the work body maps snapshot failures, close releases the root lease and binds its own cleanup error, and partial projects the completed execution. A cancellation whose cleanup fails is now the shared cleanup composite with the cancellation as its primary, as runOwned produces for every other owner. * refactor(providers): keep completed values as diagnostics in runOwned and migrate four finalizers (#10691) * refactor(providers): keep completed values as diagnostics in runOwned and migrate signature, Ghidra, bundle and LLDB finalization * test(providers): run the lifecycle scenarios over every runOwned adopter shape (#10707) One table of testing.md lifecycle rows runs over partial, diagnostics, publishing and lease adopters, replacing the hand-written precedence cases it covers. * chore(lint): move runOwned's classifier baseline entry with the file |
||
|
|
b87b318ae7 |
refactor(wasm): leave WABT cancellation to the shared owners (#10796)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal The supervisor now watches for a managed runtime's out-of-memory report while output streams (JVM java.lang.OutOfMemoryError, V8 'JavaScript heap out of memory'), so a retention budget cannot hide it. ProviderOutcome gains a runtime-exhausted kind and classifyProviderOutcome maps it once. Apktool decode opts in and moves to the shared classifier; Ghidra's single-purpose output token becomes the JVM runtime option and its area matching reuses the shared table. * fix(process): keep the runtime's out-of-memory report on the memory error it supports * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): keep a shortened out-of-memory line marked as shortened * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * fix(apktool): advise the JVM limit that governs the reported memory area * fix(ghidra): read the supervisor's parsed OOM area instead of reparsing lines * fix(sqlite,capture): read V8 heap exhaustion from streamed output, not retained stderr (#10724) The SQLite worker and the Node capture decoders now declare runtime: "v8", so the supervisor observes V8's heap report as output streams. Both classifiers read the runtime-exhausted outcome instead of matching retained stderr, so a report beyond the retention budget, or one whose process then overflowed its output budget, is still reported as memory exhaustion. * refactor(evm): classify EVMole worker outcomes through the shared provider classifier (#10716) * refactor(evm): classify EVMole worker outcomes through the shared provider classifier The EVMole worker's cancellation, deadline, output budget and CPU/file-size signals now go through classifyProviderOutcome; only the prlimit launch refusal and the reserved EFBIG exit remain in its dialect. The worker is opted into V8 exhaustion scanning so a heap report names its fixed 256 MiB heap. providerOutcomeOf now reads a launch refusal only from a spawn errno, so a private-storage or carrier read errno is no longer reported as a limiter launch failure. * fix(evm): keep a stream failure's exit status and update Linux worker expectations * refactor(process): read launch refusals through the launcher identity owner * refactor(wasm): classify WABT command outcomes through the shared provider classifier (#10727) * refactor(wasm): classify WABT command outcomes through the shared provider classifier WABT's cancellation, command deadline, output budget, and inherited-limit signals now go through classifyProviderOutcome; its dialect keeps only the configuration-probe and launch-refusal unavailability and the unclassified-exit output error. A tool ended by SIGXCPU/SIGXFSZ or the memory limit is now a resource constraint instead of an output error, and a refused launch in the producer phase is reported as unavailable. The shared timeout context gains the analysis setting that selected the deadline, and the output-limit context may name its exceeded budget. * fix(wasm): keep setup guidance when a WABT version probe's output cannot be collected * refactor(providers): classify raw provider failures through one owner * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline * fix(process): carry the runtime's exhaustion report on every memory error that claims it SQLite and historical-capture memory errors recognised a streamed V8 heap report but dropped it, so a report outside retained output reached callers without its source line or omission flags. One projection, runtimeExhaustionReport, now owns that shape for the shared classifier and both consumers. Also lowers the EVMole and WABT cancellation-constructor baselines. * fix(process): keep the provider's recovery for a native-thread exhaustion report The shared classifier replaced the provider-supplied recovery with generic capacity advice whenever the JVM reported it could not create a native thread, dropping Apktool's launcher guidance and flipping retryable to true. The provider's recovery now wins; the capacity advice remains the fallback for providers that supply none. * refactor(pwntools): classify pwntools failures through the shared provider classifier (#10782) * refactor(pwntools): classify pwntools failures through the shared provider classifier pwntools' per-site classifier is replaced by pwntoolsFailureDialect for classifyProviderFailure. Command outcomes go through classifyProviderOutcome, launch refusals through launcherRefusalOf instead of a 'spawn ' syscall prefix check, the input limit through the file dialect's fileSize, and the cleanup report through commandCleanup. The shared read cancellation now carries the reader's partial observation, and resource-signal reports accept provider detail. * fix(pwntools): report a failed command's output once and expect resource_constraint for overflow The shared outcome owner already attaches the command's output as capturedOutput, so the pwntools adapter fallback no longer copies the same text into diagnostics.stdout, diagnostics.stderr and diagnostics.captured_output; diagnostics keep the exit facts. Update the overflow expectations the dialect migration missed (layout provider cleanup and over-budget rows, pwntools cleanup) to resource_constraint. * refactor(wasm): leave WABT cancellation to the shared owners WabtFailures matched any Error named AbortError as a cancellation. No WABT path produces one: reads, path checks and owned commands report cancellation as ArtifactReaderFailure or OwnedCommandFailure, which classifyProviderFailure and classifyProviderOutcome already classify with the caller's reason. The provider's two signal checks now build the cancellation with cancelledBy. Lowers the AnalysisCancelledError constructor baseline for both WABT files to zero. * fix(wasm): report a cancelled snapshot write as the caller's cancellation The private snapshot write passed the caller's signal to Node's writeFile, whose abort envelope reached the dialect's unclassified output failure once the name-based AbortError guess was removed. The write now turns the envelope carrying its own signal's reason into cancelledBy at the producer. * refactor(firmware): classify firmware failures through the shared provider classifier (#10810) Firmware producers now report their own deadline expiry: the start check, the output inventory and launcher admission throw the phase timeout where they observe the abort, and a read the phase signal cancelled reports it through the dialect's interruption. The classifier no longer rereads a cancellation's reason as a timeout. A new readCleanup hook keeps firmware's cleanup report shape. |
||
|
|
c36649a674 |
feat(managed)!: require managed Evidence fields that were defaulted only for historical Evidence (#10952)
* feat(managed)!: require managed Evidence fields that were defaulted only for historical Evidence Member inspections, comparisons, verification results and application graphs require every field their producers write. nesting_read is boolean and the bare-name comparison mode for historical observations is deleted; signature_resolution loses type-names-v1. The unavailable-metadata member result now writes assembly: null instead of relying on a default. BREAKING CHANGE: managed records missing these fields are refused as malformed; recreate the observation. * docs(managed): drop the remaining historical-omission claims for member Evidence |
||
|
|
3afd8a16ee |
feat(evidence)!: give Evidence bundles a format revision owned by one module (#10861)
* feat(evidence)!: give Evidence bundles a format revision owned by one module `src/domain/evidenceFormat.ts` owns Evidence format evolution. Bundles now carry `evidence_format: 1`; every bundle reader admits only the current revision and refuses an unmarked or other-revision bundle once, with the single recreate-observations guidance, instead of admitting earlier shapes one optional field at a time. The 6.7-era artifact inventory summary identities are no longer rebuilt: compare_artifacts checks the current projection only and reports a mismatch with the owner's guidance. The pre-6.6 identity diagnosis uses the same guidance. SQLite `worker_timeout_ms` and Dart AOT `string_pool.policy`, optional only for historical Evidence, are now required. BREAKING CHANGE: Evidence bundles written by REA 6.x (no `evidence_format`) are refused by import, comparison, reconstruction and analysis-snapshot readers as an integrity mismatch telling the caller to recreate the observations; re-exporting an earlier bundle does not update its format or identities. Bundles constructed by hand must include `"evidence_format": 1`. 6.7-era artifact summaries are refused by compare_artifacts, and SQLite and Dart AOT Evidence without the newly required fields fails validation. * fix(evidence): let the ledger application admit its bundle's format build_reconstruction_obligation_ledger registered the full bundle schema with the SDK, so an unmarked or other-revision bundle was refused as invalid_request before the format owner ran. Register it like coverage: the application parses the request envelope and admits the bundle. * feat(pcap)!: read capture Evidence through the current result schema only (#10879) Delete the pcap read-compatibility schema that defaulted executable identity for historical capture Evidence, and require query_labels_hex (null when unknown) now that every producer writes it. Evidence from an earlier format is refused at the bundle format owner; a record that omits these fields is reported as malformed instead of defaulted. BREAKING CHANGE: inspect_pcap_capture results always carry query_labels_hex, and analysis views no longer default missing tshark/capinfos identity fields. * feat(desktop)!: require the effective view policy in desktop state Evidence (#10886) inspect_desktop_application_state always records the complete policy it used, including sqlite_view_bytes. Drop the optional historical shape and the task draft's absent-policy branch. BREAKING CHANGE: desktop application state results without effective_view_policy, or with a policy missing sqlite_view_bytes, are refused as malformed. * feat(android)!: require component declaration facets and reference aggregates in Android Evidence (#10904) * feat(android)!: require component declaration facets and reference aggregates in Android Evidence The JADX producers always write the manifest component projection with every declaration facet, target_definition and direct_invokes_coverage. Require them, delete the duplicate observed component schema, drop the unknown declaration coverage that only described historical omission, and give manifest view results their explicit facet. BREAKING CHANGE: Android package, component and reference results missing these fields are refused as malformed; component declaration_coverage and its summary counts no longer include unknown; manifest view results always carry facet manifest. * refactor(android): parse package results with the domain schema directly * feat(browser)!: require the DOM length unit and redirect-scoped prior-hop facts (#10897) * feat(browser)!: require the DOM length unit and redirect-scoped prior-hop facts Both CDP producers always declare node_value_length_unit, and the observation session writes redirect_response on every redirect event and no other. Require the unit, drop the diff's absent-unit branch, and admit redirect_response exactly on redirect rows. BREAKING CHANGE: DOM snapshots without node_value_length_unit and redirect timeline rows without redirect_response are refused as malformed, including inline inspections passed to compare_web_captures. * docs(browser): drop the historical redirect_response omission note * feat(native)!: require native Evidence fields that were optional only for historical Evidence (#10946) Mach-O encryption, slice malformed cause, symbol runtime names and import facts; ELF export encoding facts and visibility; value-flow limits; load-image permissions and relocation symbols; Swift type-reference kind and GPU AMD target metadata are required. Legacy enum values (unrecorded, unknown visibility, undecodable, modinfo_field_exceeds_limit) and the retained schemas, view defaults and reinterpretations that served historical Evidence are deleted. BREAKING CHANGE: native records missing these fields are refused as malformed; recreate the observation. |
||
|
|
f8e8dc3e7a |
feat(cutter): name the plugin re-copy recovery for sessions whose plugin source is unknown or modified (#10950)
* feat(cutter): name the plugin re-copy recovery for sessions whose plugin source is unknown or modified * test(cutter): assert recovery names the owner's platform plugin path |
||
|
|
d0fee4e58e |
fix(mcp): re-emit advertised patterns in a portable regex grammar (#10582)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): re-emit advertised patterns in a portable regex grammar * fix(mcp): validate advertised dialect by selected profile * fix(mcp): preserve schema widening through references * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns * fix(mcp): keep references valid when presentation widens their targets * fix(mcp): relax references into negations and conditionals presentation may remove * fix(mcp): keep astral literals and dynamic references widening in every mode * fix(mcp): omit astral literals and relax untracked references when presentation widens * fix(mcp): read reference pointers by schema position, not segment spelling * fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse * fix(mcp): omit patterns whose classes name astral characters * fix(mcp): decide union collapse and pointer protection from canonical branches * docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes * test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe * fix(mcp): protect references into unevaluated keywords lost evaluation removes * fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings * fix(mcp): protect references into literal siblings of relaxed draft-07 references |
||
|
|
d044f44d91 |
feat(setup): inspect, refresh and remove five mcp-add-only clients (#10694)
* feat(setup): give five mcp-add clients one client-table row Cline VS Code extension, Kiro, Mastra Code, Zed and Amp move from registration-only catalog entries to rows in the client table. rea mcp add projects those rows, so doctor, update and uninstall now inspect, refresh and remove what it wrote, and setup offers each client when detected. Refs #7181 * refactor(setup): keep FreeBuff's comment on its declaration The client helpers added for the folded mcp-add clients were inserted between FreeBuff's profile-directory comment and its declaration. Move them above it, and drop an import the folded locations no longer use. * test(setup): refresh an older mcp-add registration through setup Address review: seed each folded client with an older REA-owned package runner launcher, then check that doctor reports it stale, update selects it, setup plans and applies the update, and doctor then reads the current launcher. * fix(setup): register Amp in settings.jsonc when that is its settings file (#10717) Amp reads ~/.config/amp/settings.json or settings.jsonc. REA always used settings.json, creating a second file beside an existing settings.jsonc. Use settings.jsonc when it is the only file, and refuse when both exist because Amp does not document which one it reads. * feat(setup): manage Cline in VS Code Insiders, VSCodium, Cursor and Windsurf (#10729) * feat(setup): manage Cline in VS Code Insiders, VSCodium, Cursor and Windsurf The Cline extension keeps its MCP settings in the global storage of whichever editor runs it. REA resolved only VS Code's, so a Cline in another editor was never configured, inspected or cleaned. Add one client-table row per editor, resolved through the shared Code-OSS user data rule, and detected where that editor's Cline settings exist. * test(setup): cover VSCODE_PORTABLE for Cline's editor hosts Address review: VSCODE_PORTABLE moves only VS Code's own storage, so the other editors keep their settings path; and the older-release note now says which hosts mcp add could register before. * fix(setup): find a Linux Flatpak Zed's configuration (#10721) * fix(setup): find a Linux Flatpak Zed's configuration Zed's config_dir honors FLATPAK_XDG_CONFIG_HOME first, and a Flathub Zed reads ~/.var/app/dev.zed.Zed/config/zed inside its sandbox. REA always wrote ~/.config/zed, which that Zed never reads. Honor the override, use the sandbox folder when it is the only one, and refuse when both a native and a Flatpak configuration exist. * fix(setup): treat an XDG_CONFIG_HOME naming the Flatpak folder as one Zed folder * fix(setup): treat linked native and Flatpak Zed folders as one configuration * test(setup): expect doctor to report the Amp registration mcp add wrote |
||
|
|
8428de13d3 |
feat(ida)!: require an explicit protocol for attached IDA registrations (#10846)
* feat(ida)!: require an explicit protocol for attached IDA registrations An attached registration (the default mode) silently selected the legacy ida-pro-mcp 1.4 GUI proxy when `protocol` was omitted. The registration schema now resolves the upstream protocol once: attached registrations must name `"legacy"` or `"native"`, headless registrations resolve to the database supervisor, and consumers read the resolved protocol instead of inferring it from `mode`. BREAKING CHANGE: an attached IDA registration without `protocol` is refused with a configuration error naming the choice. Add `"protocol": "legacy"` to an ida-pro-mcp 1.4 proxy registration (or `"protocol": "native"` for the ida-free-mcp plugin). Headless registrations are unchanged. * test(ida): name the protocol in every attached registration fixture The setup budget fixture still wrote an attached URL registration without a protocol, and the IDA registration rejection fixtures relied on the missing protocol as one of several failures. Each now names its protocol, so setup reaches its timeout checks and every rejection case fails only for its own constraint. |
||
|
|
66d1527a3d | refactor(native): parse native inventory results once at the operation port (#10880) | ||
|
|
17a5f14f98 |
fix(process): run ps from fixed system locations, not REA's PATH (#10755)
* fix(process): run macOS ps from /bin/ps, not REA's PATH Owned process cleanup and process sampling ran "ps" through REA's PATH, so an unusable PATH turned a confirmable cleanup into an incomplete one (spawn ps ENOENT). macOS ships ps at /bin/ps on the sealed system volume. Linux keeps the documented procps-on-REA's-PATH contract. * test(process): stop the ps fixture only after its descendant spawned * fix(process): run Linux ps from fixed system locations before REA's PATH Linux process ownership now runs the first executable of /bin/ps, /usr/bin/ps and /run/current-system/sw/bin/ps, searching REA's PATH only when none exists. Admission refusals name the ps that ran in their reason and ps_command/ps_source diagnostics; cleanup failure reasons keep the executed command. Doctor and remediation text follow the same selection. The macOS cleanup test now releases its fixture group even when the descendant wait fails. * fix(application): keep which ps ran in provider availability ownedProcessPrerequisiteAvailability copied only the admission and system codes from a Linux ps refusal, so Ghidra, JADX and Apktool status lost ps_command and ps_source. Copy the refusal's prerequisite facts from one key list. |
||
|
|
6a4caa065b |
refactor(providers): classify raw provider failures through one owner (#10757)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal The supervisor now watches for a managed runtime's out-of-memory report while output streams (JVM java.lang.OutOfMemoryError, V8 'JavaScript heap out of memory'), so a retention budget cannot hide it. ProviderOutcome gains a runtime-exhausted kind and classifyProviderOutcome maps it once. Apktool decode opts in and moves to the shared classifier; Ghidra's single-purpose output token becomes the JVM runtime option and its area matching reuses the shared table. * fix(process): keep the runtime's out-of-memory report on the memory error it supports * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): keep a shortened out-of-memory line marked as shortened * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * fix(apktool): advise the JVM limit that governs the reported memory area * fix(ghidra): read the supervisor's parsed OOM area instead of reparsing lines * fix(sqlite,capture): read V8 heap exhaustion from streamed output, not retained stderr (#10724) The SQLite worker and the Node capture decoders now declare runtime: "v8", so the supervisor observes V8's heap report as output streams. Both classifiers read the runtime-exhausted outcome instead of matching retained stderr, so a report beyond the retention budget, or one whose process then overflowed its output budget, is still reported as memory exhaustion. * refactor(evm): classify EVMole worker outcomes through the shared provider classifier (#10716) * refactor(evm): classify EVMole worker outcomes through the shared provider classifier The EVMole worker's cancellation, deadline, output budget and CPU/file-size signals now go through classifyProviderOutcome; only the prlimit launch refusal and the reserved EFBIG exit remain in its dialect. The worker is opted into V8 exhaustion scanning so a heap report names its fixed 256 MiB heap. providerOutcomeOf now reads a launch refusal only from a spawn errno, so a private-storage or carrier read errno is no longer reported as a limiter launch failure. * fix(evm): keep a stream failure's exit status and update Linux worker expectations * refactor(process): read launch refusals through the launcher identity owner * refactor(wasm): classify WABT command outcomes through the shared provider classifier (#10727) * refactor(wasm): classify WABT command outcomes through the shared provider classifier WABT's cancellation, command deadline, output budget, and inherited-limit signals now go through classifyProviderOutcome; its dialect keeps only the configuration-probe and launch-refusal unavailability and the unclassified-exit output error. A tool ended by SIGXCPU/SIGXFSZ or the memory limit is now a resource constraint instead of an output error, and a refused launch in the producer phase is reported as unavailable. The shared timeout context gains the analysis setting that selected the deadline, and the output-limit context may name its exceeded budget. * fix(wasm): keep setup guidance when a WABT version probe's output cannot be collected * refactor(providers): classify raw provider failures through one owner * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline * fix(process): carry the runtime's exhaustion report on every memory error that claims it SQLite and historical-capture memory errors recognised a streamed V8 heap report but dropped it, so a report outside retained output reached callers without its source line or omission flags. One projection, runtimeExhaustionReport, now owns that shape for the shared classifier and both consumers. Also lowers the EVMole and WABT cancellation-constructor baselines. * fix(process): keep the provider's recovery for a native-thread exhaustion report The shared classifier replaced the provider-supplied recovery with generic capacity advice whenever the JVM reported it could not create a native thread, dropping Apktool's launcher guidance and flipping retryable to true. The provider's recovery now wins; the capacity advice remains the fallback for providers that supply none. * refactor(pwntools): classify pwntools failures through the shared provider classifier (#10782) * refactor(pwntools): classify pwntools failures through the shared provider classifier pwntools' per-site classifier is replaced by pwntoolsFailureDialect for classifyProviderFailure. Command outcomes go through classifyProviderOutcome, launch refusals through launcherRefusalOf instead of a 'spawn ' syscall prefix check, the input limit through the file dialect's fileSize, and the cleanup report through commandCleanup. The shared read cancellation now carries the reader's partial observation, and resource-signal reports accept provider detail. * fix(pwntools): report a failed command's output once and expect resource_constraint for overflow The shared outcome owner already attaches the command's output as capturedOutput, so the pwntools adapter fallback no longer copies the same text into diagnostics.stdout, diagnostics.stderr and diagnostics.captured_output; diagnostics keep the exit facts. Update the overflow expectations the dialect migration missed (layout provider cleanup and over-budget rows, pwntools cleanup) to resource_constraint. |
||
|
|
3b17d05f9d |
docs(adr): accept parsing native operation facts once at the operation port (#10866)
* docs(adr): propose parsing native operation results once at the operation port * docs(adr): accept parsing native operation facts once at the operation port |
||
|
|
c06a0b9ee8 |
feat(pcap): read tshark JSON packets through one envelope owner with an adjustable expansion bound (#10788)
* refactor(pcap): read tshark JSON packets through one envelope owner PcapOutput and the packet-capture reader each decoded tshark -T json and checked the packet envelope. The capture reader let SyntaxError escape and accepted any shape until its field schema ran. src/pcap/TsharkJsonPackets.ts now owns the envelope (malformed JSON, the packet array, each packet's _source.layers) as typed failures, and the pcap byte and expansion budget. Both consumers map those failures to their existing error kinds. An architecture guard keeps _source.layers reads in the owner. * fix(captures): keep producer output on a refused packet reply parsePacketOutput threw AnalysisOutputError itself, so the provider's failure mapping returned it without the captured stdout and stderr, both for envelope refusals and for unordered or out-of-limit frames. It now returns a Result with the reason and cause, and the provider builds the AnalysisOutputError with capturedOutput. * feat(captures): bound packet-capture JSON expansion by an adjustable setting The capture path parsed TShark's selected-field JSON without the expansion estimate the pcap reader charges. It now reads through readTsharkJsonPackets under capture.packet_json_expansion_bytes (REA_CAPTURE_PACKET_JSON_EXPANSION_BYTES). The estimate charges at most 130 bytes per code unit and the output is one Node string, so no admissible output reaches 69,793,215,440 bytes; the default and maximum are 128 GiB, so the budget refuses only when lowered. A refusal is an adjustable_budget resource constraint naming the setting and keeps the producer output; a malformed launch seed is refused before the capture is read. |
||
|
|
b0e32578ae |
feat(cli): warn after mcp add writes Claude Desktop's configuration (#10696)
* feat(cli): warn after mcp add writes Claude Desktop's configuration rea mcp add resolves Claude Desktop from the client table, whose row says a running app can rewrite its configuration from memory, but the command never told the caller. Print that notice on stderr when it writes the file. Backup notices now use the client's display name instead of special-casing Amp. * fix(cli): warn about Claude Desktop whenever mcp add wrote its file Address review findings: a registration that failed after publication, such as cancellation during verification, still left the file written, so the running-app notice now follows the registration owner's written fact instead of overall success. The CLI test compares the delivered notice with its owner instead of freezing the sentence. |
||
|
|
4b31661441 |
fix(plist): surface repeated dictionary keys in every plist reader (#10781)
* fix(plist): surface repeated dictionary keys in keyed archive, Interface Builder, entitlement and Info.plist readers * test(plist): cover repeated keys in Interface Builder archives and entitlements (#10797) |
||
|
|
c296c91770 |
fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal (#10634)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(apktool): report the decoder JVM's heap exhaustion as memory, not a target refusal The supervisor now watches for a managed runtime's out-of-memory report while output streams (JVM java.lang.OutOfMemoryError, V8 'JavaScript heap out of memory'), so a retention budget cannot hide it. ProviderOutcome gains a runtime-exhausted kind and classifyProviderOutcome maps it once. Apktool decode opts in and moves to the shared classifier; Ghidra's single-purpose output token becomes the JVM runtime option and its area matching reuses the shared table. * fix(process): keep the runtime's out-of-memory report on the memory error it supports * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): keep a shortened out-of-memory line marked as shortened * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * fix(apktool): advise the JVM limit that governs the reported memory area * fix(ghidra): read the supervisor's parsed OOM area instead of reparsing lines * fix(sqlite,capture): read V8 heap exhaustion from streamed output, not retained stderr (#10724) The SQLite worker and the Node capture decoders now declare runtime: "v8", so the supervisor observes V8's heap report as output streams. Both classifiers read the runtime-exhausted outcome instead of matching retained stderr, so a report beyond the retention budget, or one whose process then overflowed its output budget, is still reported as memory exhaustion. * refactor(evm): classify EVMole worker outcomes through the shared provider classifier (#10716) * refactor(evm): classify EVMole worker outcomes through the shared provider classifier The EVMole worker's cancellation, deadline, output budget and CPU/file-size signals now go through classifyProviderOutcome; only the prlimit launch refusal and the reserved EFBIG exit remain in its dialect. The worker is opted into V8 exhaustion scanning so a heap report names its fixed 256 MiB heap. providerOutcomeOf now reads a launch refusal only from a spawn errno, so a private-storage or carrier read errno is no longer reported as a limiter launch failure. * fix(evm): keep a stream failure's exit status and update Linux worker expectations * refactor(process): read launch refusals through the launcher identity owner * refactor(wasm): classify WABT command outcomes through the shared provider classifier (#10727) * refactor(wasm): classify WABT command outcomes through the shared provider classifier WABT's cancellation, command deadline, output budget, and inherited-limit signals now go through classifyProviderOutcome; its dialect keeps only the configuration-probe and launch-refusal unavailability and the unclassified-exit output error. A tool ended by SIGXCPU/SIGXFSZ or the memory limit is now a resource constraint instead of an output error, and a refused launch in the producer phase is reported as unavailable. The shared timeout context gains the analysis setting that selected the deadline, and the output-limit context may name its exceeded budget. * fix(wasm): keep setup guidance when a WABT version probe's output cannot be collected * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline * fix(process): carry the runtime's exhaustion report on every memory error that claims it SQLite and historical-capture memory errors recognised a streamed V8 heap report but dropped it, so a report outside retained output reached callers without its source line or omission flags. One projection, runtimeExhaustionReport, now owns that shape for the shared classifier and both consumers. Also lowers the EVMole and WABT cancellation-constructor baselines. * fix(process): keep the provider's recovery for a native-thread exhaustion report The shared classifier replaced the provider-supplied recovery with generic capacity advice whenever the JVM reported it could not create a native thread, dropping Apktool's launcher guidance and flipping retryable to true. The provider's recovery now wins; the capacity advice remains the fallback for providers that supply none. |
||
|
|
fa53f7070a |
refactor(cli): project view-delivery inspectors from their contracts (#10600)
* refactor(cli): project view-delivery inspectors from their contracts * refactor(cli): project APK signature, desktop application and EVM inspectors from contracts (#10603) |
||
|
|
a395104168 |
fix(artifacts): report ZIP bytes the central directory does not account for (#10580)
* fix(artifacts): report ZIP bytes the central directory does not account for * fix(artifacts): validate ZIP accounting and join traversal * fix(artifacts): match an unsigned ZIP data descriptor whose CRC equals the signature The optional descriptor signature only adds a candidate layout; both layouts are checked against the recorded CRC and sizes. * fix(artifacts): keep ZIP close observable and account AES data descriptors Close joins running traversal steps instead of returning the traversal, so a caller's next step after close still rejects as unavailable. Member accounting reads through BinaryReader, and a data descriptor whose directory reports no CRC (AE-2) is matched on its sizes. |
||
|
|
1f7884b5b9 |
refactor(process): classify owned command outcomes through one owner (#10628)
* fix(pcap): report a refused tool launch as an unavailable tool When a capture read's tool launch was refused with EPERM, pcap reported it as unreadable tool output (AnalysisProtocolError) instead of an unavailable tool. Pcap also never told "not executable" apart from "missing". Add classifyLaunchFailure in src/process as the one owner of which spawn errnos mean missing (ENOENT, ENOTDIR) and which mean present but not executable (EACCES, EPERM, ENOEXEC, EISDIR). Pcap, apktool and gdb used three different errno lists; all three now use it. * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * refactor(process): classify Java and adb launch refusals with the shared owner (#10598) The Ghidra and JADX Java probes and adb's version probe now take missing-versus-not-executable from classifyLaunchFailure instead of their own errno checks. ELOOP and ENAMETOOLONG join the owner's missing set, so adb keeps its existing classification and both Java probes now treat a non-directory path component as a missing runtime. * fix(pcap): preserve command launch attribution * test(pcap): expect an unknown failing stage when a limited capture tool exits unsuccessfully * refactor(process): classify owned command outcomes through one owner Add ProviderOutcome, read once from the supervisor's facts, and classifyProviderOutcome, the one mapping from an outcome to a typed error. Migrate pcap and the shared artifact producer command failure (TShark, sigrok). Add the rea/provider-failure-classifier lint rule with a shrink-only baseline of per-site (cause: unknown) => AnalysisError functions. * test(lint): cover baselined files in the provider-failure classifier rule * fix(pcap): attribute a limited capture's exit through the prlimit wrapper * fix(process): identify the refused executable for every launcher shape Name the executable on errnos Node throws synchronously from spawn (ENOEXEC, ENOTDIR, ...) and read the Windows native launcher's executable-launch constraint, so pcap attributes those refusals to the selected tool or limiter instead of an unknown stage. * test(pcap): prove synchronous launch naming with ENOTDIR on every POSIX host * refactor(process): build classified cancellations with cancelledBy and the carried caller reason * chore(lint): count runOwned's close-failure mapper from main in the classifier baseline |
||
|
|
52d6725d63 |
fix(cutter)!: report undeclared output truncation and document generation as unknown (#10726)
* fix(cutter)!: report undeclared output truncation and document generation as unknown cutter_command filled a missing output_truncated with false and a missing document_generation with the caller's expected_generation, so a reply that did not declare them read as "nothing omitted" and "document unchanged". Both are now null when the plugin did not declare them, with an Evidence limitation for each. A command that never started still reports output_truncated false, because there was no output to omit. The packaged plugin now declares output_truncated on every command reply and the current generation on its not-started replies. BREAKING CHANGE: cutter_command's result fields output_truncated and document_generation are now nullable. A caller that read document_generation as a number must handle null by listing Cutter sessions again before choosing an expected_generation. A caller that read output_truncated as a boolean must treat null as "the output may be incomplete". * test(cutter): cover the unknown-truncation limitation |
||
|
|
0c38229dd3 |
feat(cutter): identify the running plugin's source and refuse a modified one (#10731)
* feat(cutter): identify the running plugin's source and refuse a modified one The Cutter plugin now publishes the SHA-256 of its own file on its session descriptor (an additive field). Discovery reports each session's bridge_source as packaged, modified, or unknown (an older plugin without the field). cutter_command refuses a modified plugin before sending anything and names the packaged plugin to copy into Cutter's plugins/python directory. * fix(cutter): report an unreadable packaged plugin instead of hiding the live session * test(cutter): give the discovery fixture sessions their bridge source |
||
|
|
12dd3d38ac |
fix(artifacts): honor record-and-continue for lipo and FAT slice disagreement (#10732)
* fix(artifacts): honor record-and-continue for lipo and FAT slice disagreement * fix(artifacts): keep recovered slice names distinct, lipo field evidence, and unknown coverage without a FAT parse * fix(artifacts): keep lipo's unnormalized CPU declarations when FAT ranges are authoritative |
||
|
|
4673457de2 |
fix(plist): record dictionary keys declared more than once (#10737)
* fix(plist): record dictionary keys declared more than once before decoding collapses them * fix(plist): bound repeated key names in the limitation and mark only real omissions |
||
|
|
a090fa7098 |
fix(il2cpp): report the exceeded native-link maximum in the public refusal (#10741)
* fix(il2cpp): report the exceeded native-link maximum in the public refusal * fix(il2cpp): report each native-link budget's maximum in the unit its producer counts * refactor(elf): report pointer relocation failures through ParseFailure (#10748) |
||
|
|
2e1e6593f2 |
refactor(application): own the finalization precedence in runOwned (#10645)
* refactor(application): own the finalization precedence in runOwned runOwned runs owned work, closes its owner and applies the documented precedence once: a recorded failure stays primary, cancellation before commit keeps the completed value as a partial observation, cancellation after commit keeps the value, and unconfirmed cleanup reports cleanup_incomplete while keeping the completed value. finishAnalysisCommand now projects its Finalized outcome; its 31 callers are unchanged. * fix(application): preserve finalization outcomes * fix(application): classify finalization by the primary error and keep cancellation through recovered publication A producer composite whose primary is a cancellation finalized as failed because the kind read only the top-level error class; it now follows primaryAnalysisError. A cancellation that arrived while a recovered value's publication failed was dropped because the signal was read before that last await; it is now attached to the publication failure as a secondary. * fix(cli): keep the initial failure snapshot whenever close itself succeeded |
||
|
|
89640a446a |
fix(parsers): stop reading every RangeError as a format failure (#10602)
* refactor(parsers): report format failures through one ParseFailure algebra Add ParseFailure (malformed, truncated, unsupported, limit, with format, offset and field) and its one carrier, ParseFailureError, in the domain. BinaryReader now names truncation and the field it read, and its native format and resource failures are ParseFailureError subclasses. Providers projected a format failure with their own instanceof ladder, and some dropped the selected path from the invalid_format message. parseFailureAnalysisError now owns that projection for the native, Go, devicetree, V8, Windows Shortcut and Electron fuse providers. The V8 code cache, Windows Shortcut and Electron fuse format classes are removed in favour of the algebra. The architecture guard counts raw Buffer and DataView reads, plain Error throws in parser folders and plain JSON.parse of parser input against baselines that can only shrink. * fix(parsers): stop reading every RangeError as a format failure Mach-O, Swift and Objective-C metadata parsers threw RangeError for a truncated or malformed record, so their catch sites treated any RangeError as a partial decode: a call stack overflow or a host string limit became an "unresolved" metadata reason, and the IL2CPP Mach-O path reported it as a malformed container. Those parsers and the CIL method body reader now throw ParseFailureError. hostRangeErrorKind is the one interpreter of a host RangeError (stack overflow, host capacity, raw out-of-bounds read), and parseFailureFromCause admits only a parse failure or a raw out-of-bounds read as evidence about the input. Fixup stream catch-alls rethrow host limits. The architecture guard counts the remaining direct instanceof RangeError checks. * fix(parsers): preserve Apple metadata failure ownership * test(architecture): shrink parser failure baseline * fix: preserve uncertainty for host range errors |
||
|
|
da53dce1f7 |
refactor(cli): project Go, V8 and delivery inspectors from their contracts (#10576)
Migrate inspect-go-binary, inspect-v8-code-cache, inspect-devicetree and inspect-native-exports onto the contract command description and delete their hand-written options and input spreads. The description gains evidenceDelivery. It adds the shared --detail and --evidence_output options, and the run context carries the selected delivery. A contract detail field selects that delivery and is not passed to the analysis, as the hand-written commands did. Go's cross-field budget rules stay with the service's contract parse, so standalone --max-string-literals still returns invalid_request. The parity guard accepts the declared CLI-only delivery options as the only options without a contract field. |
||
|
|
6c062c9c2a |
fix(setup): stop writing the default compact input profile for Kimi and LM Studio (#10559)
* fix(setup): stop writing the default compact input profile for Kimi and LM Studio The server already advertises compact input schemas when REA_MCP_INPUT_SCHEMA_PROFILE is unset, so setup no longer adds that value to Kimi Code and LM Studio registrations, and doctor/status no longer report a registration without it as stale. Explicit stored or setup-environment profiles are still preserved. Refs #10514 * fix(setup): validate LM Studio registration environment * test(hopper): retry cleanup after confirmed application exit |
||
|
|
a22fb6e60b |
fix(model): report malformed GGUF and Safetensors headers as invalid_format through ParseFailure (#10667)
* refactor(model): report GGUF and Safetensors format failures through ParseFailure * fix(model): report malformed model headers as invalid_format through the shared mapping Malformed and truncated GGUF and Safetensors headers now take the shared ParseFailure mapping (invalid_request, invalid_format on path) instead of the model provider's own BinaryTargetError file_format_rejected. Unsupported forms stay unsupported_target and model allowances keep their resource-constraint recovery. |
||
|
|
2705aad365 |
fix(il2cpp): select universal binary slices through the shared Mach-O selection (#10661)
* fix(il2cpp): select universal binary slices through the shared Mach-O selection * test(il2cpp): assert selection facts instead of full sentences |
||
|
|
959af004df |
docs: refuse literal tool counts in living prose (#10585)
* docs: refuse literal tool counts in living prose docs:check now refuses a count of ten or more tools in README, AGENTS, CONTRIBUTING, docs/ (except dated releases, specs, verification and ADR records), the authored skill and the public website. The catalog owns that number and every hand-written copy goes stale when a tool is added. The three current statements (240, 172 and 254 tools, all measured on earlier builds) now refer to the catalog of the measured build instead. * fix(docs): exclude generated pages from prose checks * fix(docs): rerun the tool-count check when any scanned prose changes The docs:check:built cache inputs and the CI docs lane did not cover AGENTS.md, CONTRIBUTING.md, every .agents/skills tree or website/public, so an edit there could reuse a cached pass or skip the docs job. The scanner now owns one isLivingProsePath predicate; the CI plan selects the docs lane with it, and a test binds the turbo inputs to the scanned roots. |
||
|
|
b342254f9a |
refactor(macho): read universal Mach-O slices only where admission selected them (#10642)
Hopper and native dispatch metadata re-ranked FAT slices from the target's architecture name instead of reading the admitted universalSlice. Both now consume the admitted range and refuse when it is missing or undeclared. Mach-O load-command codes move to one table with an architecture guard. |
||
|
|
f3b697da5a |
refactor(cli): derive contract-backed command options from the tool contract (#10571)
* refactor(cli): derive contract-backed command options from the tool contract Each contract-backed CLI command restated its contract's input fields as hand-written incur options and mapped them back to snake_case input with conditional spreads. Nothing checked that the two schemas agreed. Add registerContractCommand: a per-command projection names only what the CLI spells differently (positionals, caller-relative path fields, option renames, CLI help wording, omitted optional fields with a reason). Option schemas, decimal argv tokens and the contract's cross-field rules are derived from the contract input schema, and parsed options map back to the contract input mechanically. Migrate inspect-sqlite-database and the thirteen flat binary-diagnostics inspectors. Their --schema output is unchanged apart from property order, and help lists options in contract order. Delete the SQLite superRefine that mirrored the contract and the per-command spreads. Add a parity test: every projected command exposes each contract field or declares its omission, and each field admits exactly what the contract admits for empty, NUL, relative-path, bound and numeric-spelling probes. * refactor(cli): refuse unprojected contract input forms at registration Address review findings on the contract projection: - Bind inspect-sqlite-database to its contract by name instead of catalog position. - Accept only field forms argv can carry (string, number, boolean, enum, and arrays of strings or enums) instead of rejecting a short list, so arrays of objects, tuples and other forms fail at registration. - Refuse root input keywords other than the projected object constraints and presentation annotations, so a contract rule such as `not` cannot disappear from --schema. * refactor(cli): describe contract commands independently of the CLI framework Split the contract projection into a framework-neutral description and a thin Incur adapter, so a later REA-owned CLI layer (#10583) can render the same description. - contractCliDescription.ts derives each positional and option from the contract and projection: key and short flag, help, argv admission schema, boolean-flag/repeatable/decimal/caller-path facts, object constraints renamed to CLI keys, the optional argv-time cross-field check, and the mapping back to contract input. - contractCommand.ts only renders that description as Incur args and options and runs the handler. Cross-field rules now refuse at argv parsing only when a projection asks (inspect-sqlite-database does, keeping its behavior); otherwise the service's contract parse refuses them as before. Exact-optional fields are projected as optional because argv cannot carry an explicit undefined and Incur's help reads flag and choice types only through optional. The parity guard reads the descriptions, and also checks that boolean fields parse as bare flags and that no projected field stays exact-optional. |
||
|
|
ef1b92bf1e |
test(mcp): check advertised schemas against a portable dialect in every profile (#10567)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): validate advertised dialect by selected profile * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns |
||
|
|
85da0bd4ee |
refactor(errors): require a reason for every analysis cancellation (#10566)
* refactor(errors): require a reason for every analysis cancellation Add cancelledBy, the one constructor for AnalysisCancelledError. Its reason argument is required: an aborted signal, an earlier cancellation, a reason carried from an inner failure, or an OwnerCancellation when REA closed the work's owner itself. Closed adb, apktool, firmware, sqlite, gdb, web-bundle analyzer and binary-session record owners now report OwnerCancellation.ownerClosed instead of an absent reason. Firmware's predecessor wait returns its cancellation as a Result, removing an unreachable reason-less fallback. An architecture guard rejects new direct constructions, with a counted per-file baseline that can only shrink. * refactor(errors): share one aborted-signal predicate with cancelledBy * refactor(process): return a departing caller's reason from a shared startup wait * refactor(providers): build decompiler-provider cancellations with a required reason (#10587) Migrate every AnalysisCancelledError construction under src/ghidra, src/ida, src/cutter, src/jeb and src/kuna to cancelledBy and lower the guard baseline from 671 to 572. Closed Kuna target commands report OwnerCancellation.ownerClosed instead of an absent reason, and Kuna and JEB close abort their lifetimes with that typed reason. * fix(errors): read the reason of any signal-shaped cancellation source * test(ci): cover the counted-baseline comparison behind the architecture guard |
||
|
|
2f4c588584 |
fix(artifacts): require each reader traversal to declare its coverage (#10572)
* fix(artifacts): require each reader traversal to declare its coverage * docs(artifacts): state that silent traversals report unknown coverage |
||
|
|
57150091d2 |
fix(ghidra): name the declared-seed recovery when no function covers an address (#10623)
Problem: code that Ghidra auto-analysis never reaches, such as DOS MZ handlers stored only in runtime-filled dispatch tables, has no Ghidra function. procedure_* lookups then returned a plain procedure_not_found whose remediation pointed only at list_procedures, and resolve_containing_procedure returned not_in_procedure with no caveat. Neither outcome named the supported recovery: declaring the entry as a function seed in REA_GHIDRA_SEED_FILE. Fix: one Ghidra-owned recovery, ghidraFunctionSeedRecovery(source), names the seed mechanism without claiming that the address holds code. It follows the session source, because seeds apply only to a fresh import: selected projects and owned checkpoints name the setting to unset first. The procedure_not_found remediation appends it. A not_in_procedure resolution now carries ghidraNotInProcedureLimitation, attached through the same absence-caveat path as the empty-reference caveats and read from the domain containing-procedure parser. outside_segments and found results are unchanged. The installation guide's seed section says where the recovery appears. Validation: src/ghidra/GhidraProvider.behavior.test.ts fails on the base (4 failed, 291 passed: both procedure_not_found rows lack the setting, the selected-project row lacks the fresh-import seed recovery, and not_in_procedure has no seed limitation) and passes after the fix (295 passed). npm run check:fast passes. Real Ghidra, including seeding real-mode DOS linear addresses, was not exercised. Refs morluto/rea#3767 |
||
|
|
e83e3fa8a0 |
feat(errors): type refusals at the producer with a total recovery (#10577)
* feat(errors): type refusals at the producer with a total recovery A resource refusal without authored text fell back to resource-kind advice: a fixed parser ceiling reported as memory told the caller to add host memory, an upstream IDA reply ceiling pointed at REA's MCP transport, and a fixed Kuna text ceiling reported as capacity was marked retryable. An ambiguous selector was reported as invalid input that pointed at the schema. Add AnalysisRefusal with three variants built from facts producers already own: fixed_ceiling (FixedAllowance, now with limit, unit and narrowing), adjustable_budget (AnalysisSettingLimit) and ambiguous_selector (new AnalysisInputError option). Each variant is attributed to the error's operation and projected under details.refusal. Presentation is a total switch over the variants, and authored text still takes precedence. Migrate the first producers. GraphQL nesting, Playwright trace input, the Kuna function text and the IDA upstream reply become fixed ceilings. jadx overloads and Kuna ambiguous names become ambiguous selectors, replacing the two Kuna-specific ambiguity texts. Seven occupied admissions declare measuredExhaustion. The rea/typed-resource-refusal lint rule rejects new untyped resource constraints, and the remaining 24 are counted in a baseline that can only shrink. * fix(errors): honor refusal recovery ownership |
||
|
|
a0d9025202 |
refactor(parsers): report format failures through one ParseFailure algebra (#10593)
* refactor(parsers): report format failures through one ParseFailure algebra Add ParseFailure (malformed, truncated, unsupported, limit, with format, offset and field) and its one carrier, ParseFailureError, in the domain. BinaryReader now names truncation and the field it read, and its native format and resource failures are ParseFailureError subclasses. Providers projected a format failure with their own instanceof ladder, and some dropped the selected path from the invalid_format message. parseFailureAnalysisError now owns that projection for the native, Go, devicetree, V8, Windows Shortcut and Electron fuse providers. The V8 code cache, Windows Shortcut and Electron fuse format classes are removed in favour of the algebra. The architecture guard counts raw Buffer and DataView reads, plain Error throws in parser folders and plain JSON.parse of parser input against baselines that can only shrink. * fix(parsers): retain malformed range offsets |
||
|
|
81c115b4c3 |
fix(setup): register mcp add clients from the shared client table (#10591)
Table-backed add-mcp agents now project their client-table row instead of redeclaring format, display name and profile in a second table. The row also carries add-mcp aliases and project documents. mcp add now applies the read-scope rules setup already enforced: Gemini settings policy blocks, the Claude Desktop MSIX write blocker and MSIX AppData redirection. |
||
|
|
5732aad077 |
docs(client-configuration): state how doctor reads a Command Code transport
Doctor reads transport, falling back to type, and reports a remote http/sse or url-only entry as unknown rather than invalid; only a non-text tag is invalid. Refs #7650 Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com> |