Commit Graph
1266 Commits
Author SHA1 Message Date
morluto 5efaedda88 ci: run required checks on merge-queue groups (#11297)
* ci: run required checks on merge-queue groups

Add the merge_group trigger to CI and PR title validation so every required
check reports on the queued group's exact head. Group runs use exact-head
concurrency groups that pushes cannot cancel, classify the group's combined
diff from its base (a non-ancestor base fails planning), and keep the CI
required gate running when a group is cancelled so it fails instead of
reporting a skipped check. Title validation checks every squash commit
subject between the group base and head.

* ci: read the merge-group comparison from a file
2026-11-15 11:29:13 -05:00
morluto f82e2eb693 fix(verify): give the macOS checkpoints lane a fixture whose DWARF Ghidra can read (#11216) 2026-11-16 00:19:07 +08:00
morluto 76c71f0dbd refactor(verify): keep each counted guard's baseline in its own file (#11316)
Every counted-baseline change edited scripts/verify/architecture-guard-baselines.json, so PRs touching unrelated guards conflicted there. Each guard now keeps its baseline in scripts/verify/baselines/<guard-key>.json with paths sorted by code unit; --shrink-baselines rewrites, and deletes a guard's file when its last count is removed, and the guard rejects unsorted files and files that name no counted guard.
2026-11-15 11:14:59 -05:00
morluto fdf856ab84 refactor(verify): give the native verifiers' roots to VerifierFixture (#11180)
* refactor(verify): give the native verifiers' roots to VerifierFixture

* fix(verify): report every nested JEB cleanup failure reason

* test(verify): give the isolated ADB verifier runs the fixture owner it now imports
2026-11-16 00:06:34 +08:00
morluto 0f53849160 feat(javascript): make the member-mutation work allowance a runtime setting (#11181)
* feat(javascript): make the member-mutation work allowance a runtime setting

The member-mutation alias-state allowance from #11144 was a fixed constant, so a refused source could not be admitted without a code change.

Register javascript.member_mutation_alias_states (default 524288, 1 to 8388608 alias states) with the launch seed REA_JAVASCRIPT_MEMBER_MUTATION_ALIAS_STATES. The application, web bundle and reference-source boundaries resolve it from the accepted operation snapshot and launch environment, refuse a malformed seed before analysis, and send it to the workers with each source. A refusal names the setting, its effective value, source and range, and the recovery; worker parents rebuild it from the allowance they sent.

Refs #8294

* fix(javascript): keep the setting and recovery of a refused web script

A web bundle script refused by the member-mutation allowance kept only its reason and reported limits, so the public unknown lost the setting, value, source and recovery. Carry the refusal's structured limit and remediation on the per-script result and its javascript_analysis unknown, grouping scripts only when that recovery agrees. Assert structured limit facts and the owning formatter's recovery instead of fixed wording.

* fix(browser): keep only registered setting limits on a refused web script

* feat(javascript): keep syntax facts for a source whose member-mutation phase is refused (#11187)

* feat(javascript): keep syntax facts for a source whose member-mutation phase is refused

A source refused by the member-mutation work allowance during static analysis lost every fact, so the application graph counted it as skipped. Reference-source import failed outright on such a file.

Checkpoint the parser, comment and text facts the static owner can still state, with parse status partial, examination not-examined and refused_phase member-mutations, before reporting the refusal; the semantic phase is not started because it indexes the same mutations. Reference-source import keeps the file's declaration-level imports and records that its CommonJS require calls were not examined.

Refs #8294

* test(javascript): compare the reference-source refusal with its owning formatter

* feat(javascript): keep a refused web script's parse and text facts

A captured script whose member-mutation phase was refused lost every fact in analyze_web_bundle, so it was neither counted as parsed nor kept its vendor markers.

The analyzer now returns the script as unavailable with partial facts: refused phase, parse status and the inferences read from script text alone. Findings gathered before the refusal are dropped, because they may have read an incomplete mutation index. The worker parent states the refusal and its setting recovery from the allowance it sent, through the same helper the isolated analyzer uses for every unavailable script. The bundle counts the script as parsed, keeps its text inferences, and its javascript_analysis unknown carries refused_phase.

Refs #8294

* chore(mcp): record the member-mutation setting in the advertised summary

* fix(javascript): rebuild a parked source worker when the member-mutation allowance changes

A worker parked on a resource scope was reused when heap, timeout and precision matched, but its requests carry the allowance it was built with. After update_analysis_settings accepted a new allowance, the next analysis on that scope kept the old one.

The reuse check now compares the allowance's value and source, so a changed setting gets a worker built with it. The web bundle worker already takes the allowance per script.
2026-11-16 00:05:14 +08:00
morluto 94c260017a refactor(verify): give the remaining verifiers' roots to VerifierFixture (#11184)
* refactor(verify): give the remaining verifiers' roots to VerifierFixture

* fix(verify): let the loader-relocation supervisor dispose itself so a retried stop can observe its exit

* test(verify): give the isolated bridge-sources and packaged-wasm runs the fixture owner they now import

* test(verify): observe the Bun and Go verifier roots where VerifierFixture loads them
2026-11-16 00:04:05 +08:00
morluto e09bbcaf5f refactor: report NativeAOT, Interface Builder and owned-MCP output limits through the shared limit owners (#11194)
* refactor: report NativeAOT, Interface Builder and owned-MCP output limits through the shared limit owners

* refactor(errors): carry a parser's required value on its limit reference and in adjustable-budget refusals (#11201)

* fix(android): keep the JADX output-limit refusal's retained process output

* refactor(native): name PE and native-export allowances in the BinaryResourceFailure limit (#11253)

PeImportLimitFailure, PeLoadConfigLimitFailure and NativeExportLimitFailure kept a parallel `limit` field beside the LimitRef their BinaryResourceFailure base already carries (named only "structure"). The allowance name now lives in the LimitRef, consumers read it with binaryResourceAllowance against the parser's exported allowance list, and the three subclasses are removed. The local-limit-error-class guard also counts limit subclasses of BinaryResourceFailure.
2026-11-16 00:02:47 +08:00
morluto f7706a199c fix(verify): recognize the ownership ps inventory from the process owner's arguments (#11291)
* fix(verify): recognize the ownership ps inventory from the process owner's arguments

* fix(verify): match the recorded-crash ps inventory against REA's fixed ps locations
2026-11-16 00:01:18 +08:00
morluto 90ce8bae4a fix(javascript): report version-comparison coverage unknown when a source graph cannot tell (#11206)
* fix(javascript): report version-comparison coverage unknown when a source graph cannot tell

* refactor(javascript): name the unavailable-graph coverage mapping once

* fix(javascript): give the version change graph and its edges the same unknown coverage

* fix(javascript): report export-shape comparison coverage unknown when a source graph cannot tell (#11218)

* fix(javascript): report export-shape comparison coverage unknown when a source graph cannot tell

* test(javascript): keep unknown export-shape coverage beside a truncated projection

* fix(javascript): read runtime-reconciliation input coverage once and report unknown when a static graph cannot tell (#11230)

* fix(javascript): read runtime-reconciliation input coverage once and report unknown when a static graph cannot tell

* fix(javascript): keep a known input truncation beside unknown reconciliation coverage

* fix(javascript): report export-shape source omission counts unknown when a side has no projection (#11261)

compare_export_shapes reported left/right_omitted_fields and omitted_property_coverage as 0 for a side whose export selection recovered no return-shape projection (missing, ambiguous or unavailable), while the sibling source_omitted_variants already reported null. Add Known<T> (src/domain/known.ts) and read each side's source coverage once through it; the counts are now null (unknown) with a limitation naming why. The runtime-reconciliation graph's omission sum and its parallel 'omissions known' flag become one Known<number> via sumKnownCounts (no output change).
2026-11-15 23:59:23 +08:00
morluto 8b7829e385 fix(verify): run the native-calls hardened-runtime check in the artifact CLI environment (#11236)
* fix(verify): run the native-calls hardened-runtime check in the artifact CLI environment

* fix(verify): give the native-calls get-task-allow copy its dSYM
2026-11-15 23:58:09 +08:00
morluto 7aea9843bc refactor(mcp): register service-backed tools through one contract binding loop (#11264)
* refactor(mcp): register service-backed tools through one contract binding loop

registerContractTools registers every bound contract from the registry through the shared Evidence or retained-summary handler its binding selects, and refuses a binding that names no registered contract. createServer declares the bindings by exact contract name; 41 per-tool register files are deleted.

* refactor(mcp): bind service-backed tools from one shared table and make each binding select one handler

serviceToolBindings owns the binding of every service-backed contract, keyed by its service; createServer and the MCP tests bind from it, so tests exercise the production handler kind, admission and dependencies. A binding can no longer carry both run and summary. The Go real-binary workflow follows the new registration owners.

* test(mcp): assert binding exclusivity with type-level checks that hold under every checker
2026-11-15 23:55:31 +08:00
morluto b41fe5a238 fix(release-exposure): count scan limitations past the cap instead of dropping them silently (#11267)
inspect_release_exposure kept the first eight scan limitations and dropped the rest with no count, at the collector and at two merge points that prepend a reason. Add boundedList/BoundedListCollector (src/domain/boundedList.ts), which always carry the omitted count, and report it as a 'limitations' coverage.omitted entry. A counted constant-maximum-slice guard keeps new .slice(0, MAX) copies from appearing outside the owner.
2026-11-15 23:54:42 +08:00
morluto 500c1f46b1 refactor(mcp): derive every advertised tool through one owner (#11268)
* refactor(mcp): derive every advertised tool through one owner

The server's registration and tools/list rewrite, catalog identity and the
Copilot verifier each assembled the advertised description, input and
output schema themselves. src/contracts/advertisedTool.ts now owns that
composition; served environment catalogs (MCP listing and card) go through
the same owner's dialect projection, keeping argument descriptions.

* test(mcp): pin each remaining environment dialect violation to its query union
2026-11-15 23:54:01 +08:00
morluto 86537a11be perf(verify): bound the agent evaluation's version probe by its command budget (#11277) 2026-11-15 23:50:12 +08:00
morluto a93a9f43c9 test(support): copy isolated-repository scripts with their runtime import closure (#11281)
* test(support): copy isolated-repository scripts with their runtime import closure

* fix(test): resolve package imports to the file Node loads in the import closure
2026-11-15 23:49:11 +08:00
morluto 3d67404132 refactor(domain): charge resource allowances through one Budget owner (#11293) 2026-11-15 23:47:20 +08:00
morluto c931ba43ab fix(managed): report a managed graph over an unavailable source as unknown (#11280) 2026-11-15 10:34:17 -05:00
morluto ac9064b394 fix(cli): treat ENOTCONN on stdout as a closed reader (#11275) 2026-11-15 10:22:40 -05:00
morluto ef77be17d2 fix(verify): report the agent evaluation's retained run root one level deep (#11273) 2026-11-15 10:19:25 -05:00
morluto 664fab7470 chore(mcp): record the selector schemas from #10753 in the advertised summary
#10753 changed 26 tools' advertised input schemas without regenerating the
committed catalog summary, so verify:advertised-schemas failed on main.
2026-11-15 09:12:15 -05:00
morluto b4cc1c998b test(mcp): record the advertised-schema summary per tool (#11192)
summary.json held every advertised pattern's site list and every tool's
schema digests in one file. Each new path-taking tool appended to the
shared path pattern's list, so concurrent tool PRs conflicted on it, and
updating it required a local build.

Each tool's digests and patterns now live in
scripts/verify/advertised-schemas/tools/<tool>.json. The check still prints
aggregated review lines such as "N tool schemas gained pattern /.../", and
on failure also prints the expected contents of each missing or stale file
so a PR can commit them from CI output without building. --update-summary
writes those files and deletes summaries of removed tools. The existing
summary was split into per-tool files from its recorded data.

Fixes #11189
2026-11-15 22:11:06 +08:00
1995ab7fce fix(elf): admit Xtensa through canonical target contracts (#11178)
Admit ELF machine 94 as the canonical Xtensa family through Ghidra's header-selected import. Share generic-header exclusions between static target types and live CLI/MCP summaries, preserving ELF-only format constraints and other providers' decline paths.

Fixes #10765.
Adapted from #10774.

Co-authored-by: Josh <joshuakrishna21@gmail.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-15 22:09:41 +08:00
morluto 271e375924 refactor(application): read the host from HostPlatform in the remaining application modules (#11124)
Scenario planning and plan Evidence take a required platform. Host file operations (target resolution, output trees, Windows spelling lookup, executable checks, native snapshot admission), the Linux distribution read and the process CLI adapter read HOST_PLATFORM explicitly. ByteEntropyService takes an optional platform seam, so its Windows casing test injects win32 instead of stubbing process.platform. src/application no longer reads process.platform or process.arch.
2026-11-15 22:03:14 +08:00
morluto 6eb0e3dac6 refactor(native): report bounded string reads that stop at their allowance as decode limits (#11174)
* refactor(native): report bounded string reads that stop at their allowance as decode limits

* fix(verify): count generic and multi-line plain-Error limit classes
2026-11-15 22:02:20 +08:00
morluto 011cd93619 refactor(verify): give the package and release verifiers' roots to VerifierFixture (#11175)
* refactor(verify): give the package and release verifiers' roots to VerifierFixture

* fix(verify): import VerifierFixture at the published-package verifier's top level
2026-11-15 22:01:49 +08:00
morluto 5c53bcaed8 feat(mcp)!: retire the full schema profiles and declare schema facts as typed annotations (#10693)
* 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.

* 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.

* docs: describe omitted output schemas as the default in README translations

* fix(mcp): select schemas in verification workflows

* 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): select complete output schemas in the Electron verifier

* fix(mcp): select complete output schemas in standalone verifier probes

* fix(mcp): keep an allOf member's tuple tail with its own positions

* fix(mcp): relax references into negations and conditionals presentation may remove

* refactor(contracts): declare root discriminators as typed schema annotations

* 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): select complete output schemas in every verifier transport

* 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): select full output schemas in packet and signal schema checks

* 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): 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): 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.

* feat(mcp)!: retire the full schema profiles and declare complete observations as a typed annotation (#10718)

* refactor(mcp): declare complete observations as a typed annotation applied only on the wire

* test(mcp): compare complete-observation declarations with their owning text

* refactor(schema): couple Zod checks with their JSON Schema constraint keywords (#10725)

* refactor(schema): couple Zod checks with their JSON Schema constraint keywords

* refactor(schema): declare pattern approximations and object output roots as typed annotations (#10754)

* refactor(schema): declare pattern approximations and object output roots as typed annotations

* fix(schema): refuse pattern declarations JSON Schema cannot state

* test(schema): select guided_workflows from its contract family

* feat(mcp)!: retire the full input and output schema profiles (#10841)

* feat(mcp)!: retire the full input and output schema profiles

The compact input presentation is now the only advertised input schema, and
output schemas are either omitted (`off`, the default) or bounded
(`compact`). Catalog identity, the build-recorded digests and the recorded
startup catalog collapse to those presentations: two digest profiles instead
of six, one recorded catalog instead of two, and no input dialect baseline.

Tests and verifiers that validated replies against listed full output
schemas now validate against the canonical output contract, which REA
already enforces server-side; tests that asserted canonical input
restrictions read the canonical input schema instead of a full listing.

BREAKING CHANGE: `REA_MCP_INPUT_SCHEMA_PROFILE=full` and
`REA_MCP_OUTPUT_SCHEMA_PROFILE=full` are refused at startup and by `rea setup`
with a configuration error naming the setting. Remove the setting from the
client registration (or rerun setup with `REA_MCP_INPUT_SCHEMA_PROFILE=compact`
/ `REA_MCP_OUTPUT_SCHEMA_PROFILE=compact`). `REA_MCP_INPUT_SCHEMA_PROFILE`
still accepts `compact`. Server-side validation is unchanged.

* test(mcp): validate replies against canonical output contracts at every listed-schema reader

tools/list omits output schemas by default, so fixtures, verifiers and the
Android analysis runners that read a listed outputSchema now bind the
canonical contract instead. connectLocalToolsMcp and advertisedMcpToolSchemas
hand the SDK a definition carrying the canonical output schema, so the SDK
client and caller-supplied validators check every successful reply.

* test(mcp): resolve Android runners' output contracts from the selected repository

The Android efficiency runners imported the canonical output-schema helper from the harness checkout while --repository selects the revision under test. Import it from the selected repository, as the runners already do for the SDK and Ajv.

* test(mcp): let Android runners compare revisions before the canonical output helper

A selected revision without scripts/lib/canonical-output-schema.mjs could not start the Android runners. Choose the output contracts in one harness helper: the selected revision's canonical contracts when it has them, otherwise its listed schemas under the full output profile it still supports.

* fix(scripts): keep caller launch settings when the real Hopper verifier builds its server environment

The verifier deleted REA_VERIFY_SERVER_COMMAND and REA_VERIFY_SERVER_ARGS_JSON from process.env itself before reading them, so a caller selecting an installed REA command silently ran the checkout's dist/main.js. Copy the environment, as main does, so only the child's environment changes.

* test(mcp): validate whole replies against canonical output contracts wherever a listed definition is held

tools/list omits output schemas by default and the full output profile is gone, so tests that handed the SDK a listed definition no longer checked complete replies. Attach the canonical output schema with withCanonicalOutputSchema at every held REA tool definition. Environment-served tools (not REA contracts), and the deferred-runtime and doctor tests that exercise per-profile listings, keep their listed definitions.

* test(mcp): record the advertised catalog summary without the retired full profiles

Retiring the full input and output profiles leaves only the compact input and compact output listings, so the summary drops the full-profile digests and every pattern only the full listings carried. Regenerated with npm run verify:advertised-schemas -- --update-summary.
2026-11-15 21:51:18 +08:00
morluto 14b6345347 fix(verify): check the ESP lanes' RISC-V toolchain through the shared prerequisite before allocating (#11143)
* fix(verify): check the ESP lanes' RISC-V toolchain through the shared prerequisite before allocating

* test(verify): require the ESP compiler probe to generate RISC-V code
2026-11-15 21:50:58 +08:00
morluto 2c7c59e14e fix(guards): refuse a counted-baseline file that is not in its written order (#11150)
* fix(guards): refuse a counted-baseline file that is not in its written order

* test(guards): decide the baseline file's rewrite or refusal in its owner and cover it
2026-11-15 21:50:38 +08:00
morluto 5e625e3139 refactor(verify): give the real-Ghidra and Kuna verifiers' roots to VerifierFixture (#11170) 2026-11-15 21:50:19 +08:00
morluto 6a3d00f85b refactor(verify): give the Windows verifiers' workspaces to VerifierFixture (#11171)
* refactor(verify): give the Windows verifiers' workspaces to VerifierFixture

* fix(verify): import VerifierFixture at the Windows native verifiers' top level, not in their child scripts
2026-11-15 21:50:00 +08:00
morluto ecf5372627 ci(guards): run the architecture guards in the pre-push check (#10948)
* ci(guards): run the architecture guards in the pre-push check

* docs(limits): name lint as the numeric-limit check's owner

* ci(lint): cache the numeric-limit check by every file its restart-field scan reads
2026-11-15 21:38:59 +08:00
morluto bd46f3c1ee test(mcp): compile advertised patterns with the regex engines clients run (#10982)
* test(mcp): compile advertised patterns with the regex engines clients run

List the built package's tools over stdio in every input, output and
catalog profile and compile each distinct advertised regular expression
with V8 (plain, u, v), Go regexp (RE2), C++ RE2, Python re, and Rust regex
and fancy-regex through the Rust jsonschema crate. A refusal names the
engine, its error, and each tool, schema path and profile.

The Python engines are pinned, hash-checked wheels; Go is the host
toolchain with GOTOOLCHAIN=local. A missing engine is reported as not
verified, and REA_REQUIRE_SCHEMA_ENGINES=1 makes it a failure.

The pattern owner now also reports patternProperties keys, which clients
compile as well.

Refs #10830

* test(mcp): run schema engine helpers and listings under the process owner

* test(mcp): load advertised schemas in the validators clients build (#10983)

* test(mcp): load advertised schemas in the validators clients build

Build a validator for every distinct advertised input and output schema
with the Rust jsonschema crate's defaults, which check the declared draft's
meta-schema and formats and compile every subschema. --complete adds Python
jsonschema's check_schema, which jsonschema.validate runs in Python clients;
it takes several seconds, so it is opt-in.

Refusals are grouped by reason, so one shared pattern that breaks many
schemas is reported once with its sites.

Ajv strict mode and OpenAI strict mode are documented as not covered, with
the reasons.

Refs #10830

* ci(mcp): require the client schema engines on every code change (#10984)

* ci(mcp): require the client schema engines on every code change

Run scripts/verify-advertised-schemas.mjs at the end of the build job, after
its artifacts upload, with REA_REQUIRE_SCHEMA_ENGINES=1 so a missing engine
fails rather than passes. Go is the runner's toolchain; the Python engines
install into a virtual environment cached by the requirements file's digest
and interpreter version. Full qualification adds --complete.

Refs #10830

* test(ci): require the client schema engine step in code builds

* test(mcp): record a reviewable summary of the advertised catalog (#10985)

* test(mcp): record a reviewable summary of the advertised catalog

Commit scripts/verify/advertised-schemas/summary.json: each advertised
pattern with the tool schemas that carry it, and a digest of every tool's
schema per input or output profile. The advertised schema check compares it
with the packaged listings it already makes and fails on any difference,
printing lines such as '119 tool schemas gained pattern /.../', so a change
that reaches many tools at once is visible in review.
--update-summary regenerates it.

Refs #10830

* docs(release): check the packed catalog with client engines before publishing (#10986)

* docs(release): check the packed catalog with client engines before publishing

Add a pre-publish step to the release guide: install the packed candidate
into an empty prefix and run verify-advertised-schemas.mjs against it with
--package-root, requiring the RE2 (Go regexp and C++ RE2) and Rust (regex,
fancy-regex and jsonschema) engines. CI checks each commit's build; this
covers the archive that will be published.

Refs #10830

* docs(release): check the exact qualified archive and clean up afterwards

* test(mcp): regenerate the advertised catalog summary from current main
2026-11-15 21:38:23 +08:00
morluto f89f82be02 refactor(verify): give the real-Hopper verifiers' roots to VerifierFixture (#11165) 2026-11-15 21:37:40 +08:00
morluto 1c90a0fcdb refactor(coverage): give the complete/partial/unknown status one owner and ratchet local completeness enums (#11134)
* refactor(coverage): give the complete/partial/unknown status one owner and ratchet local completeness enums

* fix(verify): count chained local completeness enums and exclude detail levels

* fix(javascript): keep source-to-bundle coverage unknown when an input's coverage is unknown (#11162)
2026-11-15 21:34:58 +08:00
morluto 3e4e178ccc refactor(setup): take the platform in client configuration readers and the setup write path (#11120)
* refactor(setup): take the platform in client configuration readers and the setup write path

ClientRegistrationEnvironment, ClientConfigurationFiles and SupportedClients take a required platform (before defaulted parameters). Setup's configure, inspect and alignment entry points take the setup host's platform and pass it through every layer read, ownership check and the Cordis serializer, which now aliases Windows environment names by the selected platform instead of the running host. Host file operations in ClientConfigPath, ClientConfigurationPublication, JsonFiles and rea mcp add read HOST_PLATFORM explicitly.

* fix(setup): keep private-profile modes on the host when setup selects another platform
2026-11-15 21:31:35 +08:00
morluto c966d6f49a refactor(sqlite): classify database failures through the shared provider classifier (#10870)
* 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.

* refactor(captures): classify TShark, sigrok and pcap failures through the shared provider classifier

TsharkCaptureProvider and SigrokRecordingProvider replace #failure with a dialect, and PcapProvider replaces analysisFailure and the tool-identity classifier. ArtifactAnalysisResources exposes its command context and a readCleanupFailure composer so the readCleanup hook keeps each provider's cleanup report shape.

* refactor(jeb): classify JEB failures through the shared provider classifier

JEB's raw MCP failures go through classifyProviderFailure with a JEB dialect;
a typed attribution step reports a shared phase's failure under the REA
operation. Each MCP phase deadline now reports its own interruption when it
aborts, deciding a cancellation's owner from the caller's own signal instead
of comparing abort reasons. A refusal carrying the JVM's OutOfMemoryError
report becomes a resource constraint naming JEB's Java heap.

* fix(jeb): advise the JVM limit that governs the reported memory area

* refactor(ghidra): classify Ghidra failures through the shared provider classifier

PSP extension inspection reports through classifyProviderFailure with a
Ghidra dialect. The startup deadline decides at abort time whether the shared
startup owner closed it, so Ghidra and Hopper no longer compare the abort
reason with the owner's sentinel, and Ghidra's startup no longer compares a
producer cancellation's reason with the deadline's. Three helpers that only
construct one error kind now name that kind instead of AnalysisError.

* refactor(hopper): classify original-source read failures through the shared provider classifier (#10838)

* test(ghidra): pin the aborted startup deadline over a producer cancellation

* refactor(kuna): classify Kuna failures through the shared provider classifier

Session operations, the workspace copy and the project export report raw
failures through classifyProviderFailure with Kuna dialects; the copy and
export keep their cleanup report shapes through the readCleanup hook.

* refactor(adb): report a pulled file's digest failure from its own type

* refactor(sqlite): classify worker-reply read failures through the shared provider classifier

* refactor(ida): classify IDA operation failures through the shared provider classifier

* refactor(process): let artifact-resource consumers classify through the shared provider classifier (#10867)

* test(providers): pin attribution of a cleanup-failed read's typed primary

* refactor(sqlite): classify database failures through the shared provider classifier

* refactor(ghidra): classify Ghidra failures through the shared provider classifier (#10836)

* refactor(ghidra): classify Ghidra failures through the shared provider classifier

PSP extension inspection reports through classifyProviderFailure with a
Ghidra dialect. The startup deadline decides at abort time whether the shared
startup owner closed it, so Ghidra and Hopper no longer compare the abort
reason with the owner's sentinel, and Ghidra's startup no longer compares a
producer cancellation's reason with the deadline's. Three helpers that only
construct one error kind now name that kind instead of AnalysisError.

* refactor(hopper): classify original-source read failures through the shared provider classifier (#10838)

* test(ghidra): pin the aborted startup deadline over a producer cancellation

* refactor(kuna): classify Kuna failures through the shared provider classifier (#10843)

Session operations, the workspace copy and the project export report raw
failures through classifyProviderFailure with Kuna dialects; the copy and
export keep their cleanup report shapes through the readCleanup hook.

* chore(guards): shrink the cancellation construction baseline after merging the base

* refactor(ida): classify IDA operation failures through the shared provider classifier (#10859)

* refactor(ida): classify IDA operation failures through the shared provider classifier

* refactor(process): let artifact-resource consumers classify through the shared provider classifier (#10867)

* test(providers): pin attribution of a cleanup-failed read's typed primary
2026-11-15 21:08:53 +08:00
morluto 14a5f871ae fix(verify): refuse the cross-architecture Ghidra lanes before allocating when their toolchain is missing (#11117)
* fix(verify): refuse the cross-architecture Ghidra lanes before allocating when their toolchain is missing

* fix(verify): probe the fixture toolchain through the owned command runner and check the tools' targets
2026-11-15 21:07:43 +08:00
morluto fe05a4c56d refactor(verify): release five verifier roots through VerifierFixture after their clients confirm (#11118)
* refactor(verify): release five verifier roots through VerifierFixture after their clients confirm

* fix(verify): keep the binary-layout and EVM roots until their auxiliary MCP clients confirm

* fix(verify): carry the retained root on each migrated verifier's final failure
2026-11-15 21:07:13 +08:00
morluto aec679584a refactor(verify): give the switch, Swift and address-context Ghidra workspaces to VerifierFixture (#11121)
* refactor(verify): give the switch, Swift and address-context Ghidra workspaces to VerifierFixture

* fix(verify): carry the retained Ghidra workspace on each verifier's final failure
2026-11-15 21:05:34 +08:00
morluto 682a57a987 fix(native): keep Objective-C class import coverage partial when candidate completeness is unstated (#11128) 2026-11-15 21:04:35 +08:00
morluto 28d28b0578 refactor(setup): take the platform in doctor, setup, uninstall and update maintenance (#11082)
* refactor(setup): take the platform in doctor, setup, uninstall and update maintenance

* test(setup): cover a caller-selected platform in update maintenance
2026-11-15 20:53:25 +08:00
morluto 5d4e9b8532 refactor(android): take the host in JADX configuration, doctor and workspace roots (#11086)
* refactor(android): take the host in JADX configuration, doctor and workspace roots

* fix(android): pass the host in verifiers, follow it for JAVA_HOME, and test the native cache split

* test(platform): count tests that redefine process.platform or process.arch (#11102)

Tests select a host by injection. A redefined process.platform stops exercising its branch once the module under test reads HOST_PLATFORM, and still passes. A counted baseline (105 sites in 20 files) may only shrink; each module migration switches its tests to injection.
2026-11-15 20:52:58 +08:00
morluto a8e472967b refactor(process): read Ghidra and Hopper replies through one bounded JSON-line reader (#10699)
* refactor(process): read Ghidra and Hopper replies through one bounded JSON-line reader

Both clients now share JsonLineBridgeReader: UTF-8 framing with a mandatory
reply line ceiling (bridge.max_reply_bytes, REA_BRIDGE_MAX_REPLY_BYTES,
default 256 MiB), one fatal UTF-8 policy, request-id correlation including
rejections on the reserved id 0, and typed stream failures. An oversized
reply is refused as a transport resource constraint naming the setting and
its bytes are discarded. Hopper rejections on id 0 now reach the request on
the wire instead of being dropped.

Deletes GhidraResponseRouter and HopperResponseStream.

* fix(process): bound each bridge reply by the ceiling its own request admitted

* fix(process): admit the bridge reply ceiling before launching Hopper or Ghidra

* fix(ghidra): keep a refused setting's configuration error through the provider boundary

* fix(process): admit both bridge ceilings per request as a typed configuration refusal

A malformed REA_BRIDGE_MAX_REQUEST_BYTES or REA_BRIDGE_MAX_REPLY_BYTES seed covered by a runtime override at startup is refused by the runtime view once the override is reset. Hopper and Ghidra read those getters in the request path (and Hopper re-read the request ceiling when a queued request reached the wire, outside the caller's context), so the refusal was thrown instead of returned. Both clients now copy both ceilings once at admission through readRuntimeSetting, return the ConfigurationError (Ghidra as an admission failure), and write queued requests under the ceilings they were admitted with.

* refactor(config): read rizin, gdb, Kuna, Ghidra and regex settings through readRuntimeSetting (#10795)

Each site caught the ConfigurationError a setting view throws for a malformed launch seed by hand. They now read through readRuntimeSetting and return its Result. GDB reads both debugger limits once per console command and reuses those accepted values for its limitations, timeout and diagnostics instead of re-reading the views after the command ran. Kuna's single-function read returns the refusal after releasing admission instead of throwing it. A counted architecture guard keeps the remaining hand-caught sites from growing.

* refactor(hopper): return typed bridge replies from HopperClient.callTool (#10833)

* refactor(hopper): return typed bridge replies from HopperClient.callTool

The reply contract table existed, but the provider, caller reconciliation and
regex search each applied it after callTool returned JsonValue. callTool is now
typed by method: it validates the reply against that method's contract and
returns the typed reply, or a HopperReplyContractError that names the method
and keeps the raw reply. The caller scan keeps that raw reply as its unread
page or native result. The provider dispatches list_names, file offsets and
the three reconciled operations through their literal methods, and health has
its own contract. Transport tests inject a JSON-value table for the fake
bridge's own methods.

* fix(hopper): refuse value-changing reply contracts and uninstalled methods

parseHopperReply returns the raw reply, so a contract whose input and output types differ (a coercion, default or transform) would promise a type the reply does not hold. ValueKeepingContracts refuses such a schema at compile time, for the production table and any injected one. A client whose type argument names a table it was not given now returns AnalysisCapabilityUnavailableError for a method with no installed contract instead of throwing.

* refactor(hopper): read the startup handshake through the health reply contract (#10853)

parseHopperServerInfo hand-checked each health field that hopperReplySchemas.health already defines. It now parses through that contract, keeps the zod failure as the protocol error's cause, and binds run_id to the launch.

* refactor(kuna): read the project deadline through readRuntimeSetting at each request (#10837)

* refactor(kuna): read the project deadline through readRuntimeSetting at each request

The string, call-graph and xref scans read kuna.project_timeout_ms inside the background producer they start, and the project export read it inside the shared startup promise. A malformed launch seed without an override was thrown from there and reached the caller only through the generic failure mapper; a concurrent waiter that swallows the startup promise's rejection never saw it. Each site now reads the deadline with readRuntimeSetting before starting its work and returns the refusal as that request's value; the export start returns it to each caller that needs the project, and the next request reads it again.

* fix(kuna): return a call-graph deadline refusal from analyze_function

The dossier reported any relationship failure as unavailable call coverage. A call-graph deadline refusal is the request's own setting failure, so it now returns as that ConfigurationError, as cleanup and cancellation already did.

* refactor(kuna): require the accepted project deadline on every export request

Remove acceptedExportDeadline's fallback read of the throwing configuration view. KunaProjectRequest and KunaExportRequest now require the deadline the starting operation accepted; the session passes the one it admitted through readRuntimeSetting into #lookupOrBuild. Direct cache callers in tests take it from one shared helper, withKunaProjectDeadline.

* test(mcp): carry main's Evidence-format const count (#10995) beside the bridge reply setting's

* fix(process): clean Hopper and Ghidra sessions up under the ceilings their start admitted

Cleanup requests re-admitted bridge.max_request_bytes and bridge.max_reply_bytes from the current settings. Once an override covering a malformed launch seed was reset, Hopper's shutdown_document and Ghidra's closing checkpoint_program and shutdown were refused before writing, leaving Hopper's document and files or Ghidra's JVM behind. Each session now keeps the ceilings it admitted at start, and its cleanup requests use them.

* fix(hopper): reauthenticate for cleanup under the session's admitted ceilings

The cleanup reconnect's health handshake still re-admitted the ceilings from the current settings, so a seed refused after an override reset blocked reauthentication and the shutdown after it. It now uses the same session ceilings as the shutdown requests, through one #cleanupLimits accessor.

* refactor(process): report an NDJSON line above its ceiling as a limit parse failure

Utf8NdjsonOversizeError now extends ParseFailureError<"limit"> (format ndjson, limit ndjson-line-bytes) and keeps the observed bytes the transport error reports, so parseFailureFromCause recognizes it like every other byte-format budget.
2026-11-15 20:37:21 +08:00
morluto e97b6c5282 refactor(ci): plan change scopes through an injectable Git owner (#10804)
* refactor(ci): plan change scopes through an injectable Git owner

ciChangeScope.test.ts spent about five processes per case (copy the seed
repository, git add, commit and rev-parse, then node plan.mjs with its own
merge-base and diff) to ask which lanes a path selects. Move the planner
into change-plan.mjs as planChanges(request, repository), keep plan.mjs as
the workflow entrypoint over gitRepository(), and answer the path and
package-script tables from an in-memory commit. History, renames,
deletions, push baselines, malformed metadata and GITHUB_OUTPUT keep the
Git fixture or the spawned entrypoint.

378 tests: 30.6 s elapsed and 32.6 s CPU before, 4.0 s and 4.0 s after.

* test(ci): cover workflow environment wiring through the plan entrypoint
2026-11-15 20:36:28 +08:00
morluto 483f53fdef fix(electron): refuse captures handed off to an already-running app (#10989)
* fix(electron): refuse captures handed off to an already-running app

When another instance holds the app's single-instance lock, Electron forwards the launch and its arguments to that instance. The active hook now stops the launched app at the refused requestSingleInstanceLock call and reports the refusal in its snapshot; the provider fails the capture with application_already_running before driving it.

* fix(electron): stop pending actions on a late lock refusal and keep the final snapshot

* docs(electron): describe late single-instance refusals during actions

* test(electron): join the late-refusal capture even when the test fails
2026-11-15 20:35:48 +08:00
morluto 0b95e55655 refactor(verify): give the failure-retaining Ghidra lanes' workspaces to VerifierFixture (#11097)
The m68k, MIPS, MIPS16 shared, MIPS relocatable, PowerPC, RISC-V and DOL lanes kept their mkdtemp workspace for diagnosis whenever verification or cleanup failed, and removed it with rm after success. VerifierFixture now allocates the workspace (a plain root: Ghidra children use it as TMPDIR). Every failure branch that names the retained workspace records that reason with fixture.retain, and success releases the fixture. The verifier-fixture-root baseline shrinks by 7.
2026-11-15 20:32:59 +08:00
morluto 5b5ca68bb3 refactor(verify): release the agent-experience run root through VerifierFixture (#11103) 2026-11-15 20:32:38 +08:00
morluto 97ffa67f84 refactor(setup): require the platform in client-layer readers and private-profile helpers (#11074)
* refactor(setup): require the platform in client-layer readers and private-profile helpers

* refactor(setup): drop the client-layer readers' unused host import
2026-11-15 20:21:04 +08:00
morluto b06c34031d refactor(artifacts): take the host from HOST_PLATFORM or the caller instead of process.platform (#11090) 2026-11-15 20:19:46 +08:00
morluto 3f88f69746 feat(verify): allocate kept verifier artifact directories through VerifierFixture (#11091)
The agent-client verifiers keep their lab directory as the run's artifact record (receipt, transcripts, profiles, Evidence) and name it as artifacts in the receipt, so it is not a fixture root that release should remove. VerifierFixture.keepArtifacts allocates such a directory canonically, never removes it, and names it on stderr at allocation so a run that fails before its receipt still reports where its artifacts are. The 11 client verifiers use it, and the verifier-fixture-root baseline shrinks by 11 sites.
2026-11-15 20:19:27 +08:00