Commit Graph
2487 Commits
Author SHA1 Message Date
morluto 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
2026-11-15 10:03:26 +08:00
morluto 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.
2026-11-15 09:14:56 +08:00
morluto 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
2026-11-14 19:01:15 -05:00
morluto 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.
2026-11-14 18:58:59 -05:00
morluto 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
2026-11-14 18:58:48 -05:00
morluto 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.
2026-11-14 18:58:24 -05:00
morluto 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.
2026-11-14 18:57:55 -05:00
morluto 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.
2026-11-15 04:30:18 +08:00
morluto 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
2026-11-14 15:20:31 -05:00
morluto 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
2026-11-14 15:20:03 -05:00
morluto 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
2026-11-15 04:07:21 +08:00
David Muñoz Rey 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
2026-11-14 14:52:52 -05:00
morluto 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
2026-11-14 14:36:14 -05:00
morluto 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
2026-11-14 14:35:28 -05:00
morluto 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.
2026-11-14 14:14:09 -05:00
gensokyo-devandgensokyo-dev 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>
2026-11-14 17:59:38 +01:00
wunianze666-netizenandgensokyo-dev eb0cdabfa1 docs(readme): retain packet-summary verification scope
README.md's packet-summary row says tshark/capinfos support is
Linux-verified, but sixteen translations omitted that caveat.

Fixes #7655
Supersedes #7972

The translated phrases are from #7972, reapplied to the moved pcap
guide links; simplified Chinese, which #7972 did not cover, follows the
traditional Chinese wording.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 17:59:38 +01:00
ayobamiseunandgensokyo-dev cc854f1ca1 docs(client-configuration): document Cursor, Windsurf, and Command Code targets
The client configuration reference had no entries for three clients that
the installation guide lists as supported and sends readers here for.
Add a section for each naming the configuration file setup writes, the
mcpServers.rea entry key, the entry fields, and the shared skill root, as
defined in src/application/SupportedClients.ts and
src/application/ClientConfigurationDocument.ts.

Fixes #7650
Supersedes #7750

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 17:59:38 +01:00
hhangandgensokyo-dev a7398cc9eb fix(elf): preserve compiler metadata after an empty kernel builder
Squashed from #9950 and rebased onto main.

Fixes #9942
Supersedes #9950

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 16:31:24 +01:00
wunianze666-netizenandgensokyo-dev 5e1ddec2da fix(apk): validate classic ZIP disk declarations
Squashed from #7471 and rebased onto main.

Fixes #7433
Supersedes #7471

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 16:31:24 +01:00
morlutoandgensokyo-dev 14de30ff97 fix(apple): accept historical IPS row reports
Refs #7689

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 16:31:24 +01:00
Avocadoandgensokyo-dev 0a99147c57 fix(apple): retain unknown IPS row key names
Fixes #7689
Supersedes #7733

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 16:31:24 +01:00
rodricksz4h5andgensokyo-dev 7a03182349 fix(v8): report a pre-13.4 V8 module code cache as a module
Fixes #10262
Supersedes #10263

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 16:31:24 +01:00
Cursor Agentandgensokyo-dev 1624620c2c fix(native): accept a dynsym null entry with only st_name set
inspect-native-exports treated any nonzero byte in .dynsym entry 0 as a
malformed table. That is right when the reserved slot holds a real symbol,
which was #7389, but some Android arm64 libraries set only st_name. Those
files were rejected before any export could be read.

Skip that entry, keep the inventory complete, and record the nonzero
st_name in limitations. Any other nonzero field still fails the table.

Fixes #9700

Supersedes #9752

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 16:31:24 +01:00
18b72ca461 fix(android): qualify the JNI library inventory by required splits
A base APK whose manifest requires ABI or density splits keeps its native
libraries in those splits, yet inspect_android_jni_bindings reported a
complete library inventory with zero libraries. The bridge's native
declaration inventory now also decodes the root binary manifest without a
session and reports its requiredSplitTypes and isSplitRequired facts, or why
they are unknown (bridge identity 11). When splits are required or unknown,
the library inventory is partial with an unknown that says so, and a binding
without a candidate is unknown instead of unmatched.

The binary manifest fixture from #9769 was used to check the bridge with the
real jadx-headless-mcp 0.7.1 JAR, including stripped attribute names that
resolve through framework resource IDs.

Fixes #9756

Co-Authored-By: 2SinceJuly <202121119+2SinceJuly@users.noreply.github.com>
Co-Authored-By: Phon <twilyt1@proton.me>
Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 16:15:32 +01:00
Abhishek Sharmaandgensokyo-dev 8578daf8b7 fix(native): report an unexamined thunk target in value traces
trace_native_values ended at a provider-classified thunk whose model
holds only a synthetic return (an external import) or borrows its
target's operations, without saying the target was never examined, so
a stub's small model read as the end of the call chain. Thunk targets
are now reconciled after traversal: one another path traced, attempted
or queued is left to that path, and the rest are reported in unknowns
with the target in a new optional related_procedure field.

Fixes #8476
Supersedes #8678

Based on #8678 and rebased onto main's separate call-binding module.
related_procedure is exactOptional and set only on the thunk unknown,
so other unknowns and retained traces keep their shape.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 15:32:34 +01:00
Antrulyandgensokyo-dev f8fc5be364 fix(android): classify a pre-handshake JADX heap shortage as a resource limit
A worker heap too small for REA's bridge stops the JVM before the protocol
handshake, so the launcher's retained stderr is the only evidence, and the
failure was reported as capability_unavailable with configuration advice.
When that stderr carries HotSpot's java.lang.OutOfMemoryError heap reasons,
report resource_constraint for memory with observed_max_heap_bytes null and
the same REA_JADX_HEAP_MIB remediation the bridge-reported heap failure uses,
now shared and stating -Xmx precedence. Other launcher stops are unchanged.

Refs #3517
Supersedes #3573

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 15:25:02 +01:00
2SinceJulyandgensokyo-dev 4b5d00bebd fix(desktop): ignore relative XDG bases in capture inventory
Desktop capture used XDG_* values without checking that they are
absolute, so a relative XDG_CONFIG_HOME (or data, state, cache) moved
state-directory, desktop-entry and build-secret lookups under the
working directory. The XDG Base Directory Specification says to ignore
a relative value; one xdgBase helper now applies that rule and falls
back to the home default.

Fixes #9702

Squashed from #9705 and rebased onto main. Setup's client registration
paths are left unchanged: each client's own handling of a relative
XDG_CONFIG_HOME has to be verified before REA writes elsewhere.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:59:49 +01:00
gensokyo-devandgensokyo-dev 9d2a57fd8d fix(decompile): keep each successful batch item's own limitations
A successful batch_decompile item carried no item-level provenance:
only the batch Evidence aggregated limitations, so when a provider such
as Kuna answered repeated selectors from different sources, the caveat
did not say which occurrence it applied to. Successful items now keep
their own observation's limitations (exactOptional, so retained records
still parse), and the retained items view projects them.

The batch unavailable item also dropped the provider's typed
pseudocodeAbsence reason; it now carries pseudocode_absence.

Fixes #8350

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:16:47 +01:00
wunianze666-netizenandgensokyo-dev 3e95d22dd4 fix(cli): report observe-web-session progress on stderr
MCP passes progress to observeWebSession, but the CLI did not, so a
caller of `rea observe-web-session` never saw the armed observation
window it must wait for before acting. Three CLI commands also each
wrote their own copy of the same stderr progress line.

One cliProgress module now owns the stderr progress line and reporter.
observe-web-session uses it, as do web runtime, JavaScript application
and desktop capture progress. The CDP session also stops reporting
readiness once collection is no longer active, so a stopped capture does
not invite the external action.

Fixes #8141
Supersedes #8149

Based on #8149; the desktop capture copy now shares the line writer too.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:16:39 +01:00
Avocadoandgensokyo-dev 4d02bc82b3 fix(setup): disclose manual connector steps before approval
Fixes #7692
Supersedes #7792

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:16:39 +01:00
ShuaixinHuangandgensokyo-dev 86799f919d fix(desktop): preserve ZIP member identity across bounded readers
Fixes #10172
Supersedes #10173

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:16:39 +01:00
morlutoandgensokyo-dev 1adc3fa553 fix(adb)!: preserve malformed version declarations
Fixes #7534

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:16:39 +01:00
wunianze666-netizenandgensokyo-dev 213fcc8ce1 fix(snapshot): retain schema diagnostics in file failures
Refs morluto/rea#7442

Fixes #7442
Supersedes #7875

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:06:23 +01:00
Cursor Agentandgensokyo-dev 3fbc940330 fix(ghidra): report byte-search cursor mismatches without schema repair
A cursor for another target, profile, pattern, mask, bounds, or document
was reported as invalid input and pointed at schema repair. Name the
binding, attribute the issue to the cursor, and leave the differing
component unknown.

Fixes #8366
Supersedes #8420

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:06:23 +01:00
3a1db29166 fix(native): retain the dispatch reader failure when the symbol fallback fails
When the byte reader for inspect_native_dispatch_metadata refuses a target
(for example a 32-bit Mach-O) and the list_names symbol fallback then fails
or returns an invalid inventory, only the fallback's error reached the
caller. Retain the reader failure under diagnostics.binary_metadata_failure.

Fixes #7651.

Carries forward e7884a704 (by @morluto, on @dreinst's #7701).

Signed-off-by: Zhaowei Gu <83746079+zw-g@users.noreply.github.com>

Supersedes #8036

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:06:23 +01:00
fd97d0926c fix(hopper): type the Apple Events authorization denial
A hardened-runtime client without the Apple Events automation
entitlement got generic Automation advice, and the projection kept
retryable: true, so agents retried from the same unauthorized client.
The denial is now a typed launch rejection whose message and recovery
name the entitlement and the Automation setting, with retry turned off.

Fixes #9879

Squashed from #9916 and rebased onto main.

Co-Authored-By: morluto <76467478+morluto@users.noreply.github.com>
Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:06:23 +01:00
gensokyo-devandgensokyo-dev 9d3eb083dd fix(python): pin only the 3.14 and 3.15 magics checked locally
Keep magic 3627 (CPython 3.14.6) and 3666 (CPython 3.15.0b3), whose code
layout and inline-cache tables match those interpreters' opcode tables and
whose decoded code objects match marshal.loads across a stdlib sample. Leave
the 3.15.0a8 magic 3663 unpinned, since no 3.15.0a8 interpreter was available
to check it, and regenerate the 3.15 slice fixture with 3.15.0b3.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 13:37:55 +01:00
Abhishek Sharma 1d08253ff2 feat(python): decode CPython 3.14 and 3.15 pyc code objects
Decode marshal slice constants from magic 3608 onward and pin the 3.11 code
layout and inline-cache tables for the 3.14 and 3.15 magics.

Refs #8206
2026-11-14 13:37:55 +01:00
gensokyo-devandgensokyo-dev b990eb496d perf(cli): load only the registrar a one-shot command needs
Every rea process imported and registered all 52 command registrars
(about 1,900 modules) before running any command. A one-shot command
now loads only the registrar that defines its top-level command.

- src/cli/cliCommandRegistrations.ts holds every registrar in one table,
  grouped by tool family, with its module loader and its call. The
  complete createCli registers the table with static imports, and the
  types check that each entry matches its module.
- src/cli/cliShell.ts owns what does not depend on which commands are
  registered: identity, globals, argument policy, completions and the
  registration builtins. The full and lazy paths share it.
- scripts/record-cli-commands.mjs records, after tsc, which registrar
  defines each top-level command, from the same compiled table. The
  bundle keeps the record as an external dist module.
- cli/cliLoader.ts selects the recorded registrar when a known top-level
  command runs. It loads the complete CLI for help, --schema, --llms,
  completions, builtins, unknown names ("did you mean"), or a missing
  record.
- Process-owned CLI resources register their closers when their module
  loads (cli/cliResources.ts), so the shell no longer imports
  JavaScript-analysis and guidance owners just to close them.

Measured on one pinned core (median of 5 warm runs, base main vs this
change):
- guidance: 1.95 s / 253 MB → 0.42 s / 101 MB
- list-cutter-sessions: 1.97 s → 0.49 s
- inspect-go-binary: 1.95 s → 0.95 s
- setup --dry-run: 2.40 s → 1.88 s
- analyze: 2.39 s → 1.78 s
- --help: 1.99 s → 2.04 s (complete CLI, as before)

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 20:25:11 +08:00
gensokyo-devandgensokyo-dev 55c9e8e546 test: close the wait-deadline review gaps
- doctorCancellation measured from the signal, after the probe had
  started, so a probe stopped by its own deadline could still pass. The
  fake probe now records its start, and the check runs from there.
- rea/project-wait-deadline missed literal computed `timeout` keys and
  spread options. It now reports both, as well as computed keys it
  cannot read.
- The testing guide notes that a long-running test's expect.poll keeps
  its project budget, while waitFor follows the tag's deadline.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 19:28:38 +08:00
gensokyo-devandgensokyo-dev 07e4b700ac test: let the deadline policy own test waits
Vitest's expect.poll and vi.waitFor stop after one second by default, a
host-speed guess that the project's deadline policy does not see. Under
hosted-CI load, kunaProjectConcurrency failed that way twice on unrelated
PRs. Another 256 waits relied on the default, and 97 passed literals
picked to fit some host.

Waits now take as long as their test may run, less the reporting reserve
that children already keep. Each Vitest project sets expect.poll's
default, and the new waitFor in tests/support/testWait.ts replaces
vi.waitFor. Fixture readiness waits (awaitAcknowledgement and the provider
process waits) default to the same deadline, and their host-speed literal
arguments are removed. One remainingTestDeadline owns the arithmetic for
both children and waits.

Ten waits whose short timeout was the real check now assert it directly
(Kuna version probe, Cutter discovery, doctor and Inspector cancellation,
apktool fixture teardown, JADX disconnect): settlement before the
production deadline that would otherwise also satisfy the wait, or a
deadline pinned beyond every test deadline.

The rea/project-wait-deadline lint rule rejects vi.waitFor and explicit
expect.poll timeouts. The testing guide and the CI tests audit skill now
document the policy.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 19:28:38 +08:00
chordpliandgensokyo-dev d5dd0b6fd9 fix(native): select same-family universal slices by subtype name
Fixes #9792

Squashed from #9793 and rebased onto main.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 12:13:56 +01:00
2SinceJulyandgensokyo-dev d68383f98d fix(desktop): keep denied path probes unknown instead of absent
`isHostFile` folded every stat failure into "not a file", so a library
candidate under a denied directory became a missing library, and an
unprobeable apt release file or package file read as absent.

`probeHostFile` reports ENOENT/ENOTDIR as absent and every other
failure as unknown. Apt release discovery, the package-file check and
the library walk keep those unknowns: a candidate under a directory the
linker cannot search (EACCES) is kept as a last resort and reported
unreadable rather than missing. Any other failure keeps its search
position, since glibc's open_path continues only past ENOENT and EACCES.

Fixes #9703

Squashed from #9722 and rebased onto main. Adapted on rebase: only
EACCES counts as searched past (checked on glibc 2.36, where a looping
symlink candidate ends the search), the probe reuses the domain
LibraryFileProbe type, and a stray comment is dropped.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 12:13:50 +01:00
Avocadoandgensokyo-dev 0c083b7271 fix(browser): qualify target listing coverage by transport admission
Fixes #7687
Supersedes #7746

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 12:13:50 +01:00
gensokyo-devandClaude Opus 5.5 610cdf9961 docs(kernel-modules): count the trailing newline in the signature magic
The appended-signature magic `~Module signature appended~\n` is 28
bytes, matching src/domain/native/kernelModule.ts.

Fixes #7324

Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 10:21:04 +01:00
139edb2ec6 docs(kernel-modules): align this_module statuses and trailer reason with the parser
The guide listed three `.gnu.linkonce.this_module` statuses, but the
parser and the domain schema also return `unsupported` when the section
is stored SHF_COMPRESSED. Add that status with its condition.

The guide also presented `signature_trailer_truncated` as the result for
an appended magic with fewer than 12 preceding bytes. That branch needs
a file shorter than 40 bytes, and ELF admission requires at least 52
(ELF32) or 64 (ELF64) bytes, so the supported inspection never returns
it. State that the reason is reserved and unreachable for admitted files
without changing the parser or the schema enum.

Fixes #7669
Fixes #7670
Supersedes #7758

Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 10:21:04 +01:00
cb4ffa0220 docs(devicetree): use the ev_ retained Evidence id prefix in the example
The retained-reference example wrote the Evidence id as "ev:<digest>".
Retained ids are "ev_" followed by the digest (prefixedDigestSchema in
src/domain/digests.ts), and inspect_analysis_view rejects the colon form
with invalid_format. Use the same "ev_<digest>" placeholder as the other
guides.

Fixes #7612
Supersedes #7760

Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 10:21:04 +01:00
ee3e627efb docs(ci): describe CI lanes without counts that drift
The testing guides stated lane and shard counts in prose. The counts drifted
when the workflow changed: "all eight fast built shards" survived the move to
twelve, "Eight Linux real-system lanes" now covers twelve workflow calls, and
the SQLite guide named a Node 24.15.0 lane that the matrix no longer runs.
Describe each set by its selector and point at the workflow that owns the
exact versions, so later workflow changes cannot make the text wrong.

Fixes #7616
Fixes #7617

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 17:11:50 +08:00
morluto b138f52e12 refactor: prune internal seams and preserve configuration ownership (#10430)
* refactor: prune internal seams and preserve configuration ownership

* fix(setup): keep YAML aliases and inherited registration settings on refresh

- Reuse an unchanged YAML collection only while every alias in it still
  resolves after the edit; otherwise rebuild it so the alias becomes its
  value. A sibling anchor replaced or moved in the same refresh no longer
  leaves an unresolved alias in Hermes or Goose output.
- Keep a connection selector whose existing value already chooses stdio
  (for example an inherited Hermes transport: stdio) instead of superseding
  it; remote selectors are still replaced. Explicit stdio selectors are
  therefore no longer rewritten (Kimi expectation updated).
- When the whole Hermes registration is inherited through a merge,
  override it with that merge and write only the changed fields.

* fix(setup): edit registration fields whose YAML key is an alias

A key written as an alias to a string scalar (for example *field with
field: &field env) was treated as a source-only key, so any change to
its value was refused in Hermes and Goose. Resolve such keys to their
string, keep the aliased spelling while its anchor survives the edit,
and write the plain key when the same edit rebuilds the anchor.

* test(process): bound cleanup-boundary waits and always release gates

Both cancellation tests awaited a bare started promise and released
their gates only on success, so a missed boundary waited for the outer
deadline and could leave cleanup parked. Use awaitAcknowledgement and
release and join the cleanup in finally.

* fix(setup): repair only aliases an edit leaves unresolved

Replace the pre-edit alias survival guess, which expanded aliases to
sibling anchors that survive unchanged, with an exact repair: record
what each alias in the replaced value resolves to, write the edit, then
replace only aliases left without a preceding anchor by that value.

- Keep an aliased key's source position, so its anchor stays ahead of
  later aliases.
- Treat an aliased key as its string only when no other key in the map
  resolves to the same string; an ambiguous one stays guarded.
- Override an inherited Hermes registration only when the requested
  entry keeps every inherited field, so an explicit replacement can drop
  remote selectors.

* fix(setup): repair aliases whose binding an edit changes, keeping comments

An alias whose own anchor was removed could resolve to an earlier anchor
with the same name and silently change value. Record the node each alias
resolved to and repair any alias that no longer resolves to that node.
Carry the alias's comments and spacing onto the repaired value.

* test(setup): split the Hermes anchor and merge refresh cases

* fix(setup): refuse removing an overridden key its merge would restore

The merge-retention check skipped keys the mapping also overrides, so
dropping such a key (for example a remote url during an explicit stdio
replacement) let the retained merge restore it. Check removal before
skipping overridden keys, so the edit is refused with the existing
message instead of producing a registration that cannot be applied.
2026-11-14 04:08:37 -05:00