mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
e97b6c5282a5f809db31c1ccf6891c974f3deff4
442
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5b5ca68bb3 | refactor(verify): release the agent-experience run root through VerifierFixture (#11103) | ||
|
|
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. |
||
|
|
abd36dd250 |
refactor(browser): parse Runtime and Debugger events once by registered schemas (#10742)
* refactor(browser): parse frame lifecycle events once by a registered event schema CdpConnection admits each event through protocol/CdpEvents.ts, which parses the five Page frame lifecycle events once into identity facts plus a frame URL observation, like a frame-tree node. Screenshot, page capture, the observation timeline, WebMCP, Electron inspection and the execution window read those facts instead of re-parsing the raw payload; CdpFrameFacts no longer carries the raw source record. Playwright CDP session subscriptions name an event from Playwright's protocol table, and an architecture guard counts the remaining raw event payload reads so they can only shrink. * refactor(browser): parse Runtime and Debugger events once by registered schemas Register Debugger.scriptParsed, Debugger.scriptFailedToParse, Runtime.executionContextCreated, Runtime.executionContextDestroyed and Runtime.consoleAPICalled. Script and context payloads carry both the tolerant facts passive capture uses and the active runtime's strict declaration, derived from one parse, plus the declaration's byte size for the runtime retention budget. Page capture, Electron script capture, the V8 Inspector provider and the runtime source inventory now read the registered payload. The cdp-raw-event-params baseline drops from 20 to 7. * refactor(browser): admit transport events through the registered-event owner Remove the unused cdpFrameUrl wrapper; its fragment cases now exercise observeCdpFrameUrl. Add a connection-level test that two subscribers share one parsed payload and the raw params. * fix(browser): report an unserializable event declaration's size instead of throwing JSON.stringify can throw on a declaration JSON.parse accepted (nesting deeper than the serializer's stack). The registry sized script and context declarations inside the connection's WebSocket callback, so such an event escaped as an uncaught exception. The size is now a Result; the runtime source inventory raises the failure inside its own catch, as before. * refactor(browser): parse Network events once by registered schemas (#10743) * refactor(browser): parse Network events once by registered schemas Register Network.requestWillBeSent, responseReceived, loadingFinished, loadingFailed, webSocketCreated and webSocketFrameSent/Received. The request payload carries the tolerant facts page capture and the timeline read plus the active runtime's strict declaration. Page capture's network and WebSocket handlers, the timeline's request tracking and the runtime request inventory now read the registered payload. The cdp-raw-event-params baseline drops from 7 to 5. * refactor(browser): drop payload helpers the capture handlers no longer use * refactor(browser): read every CDP event payload through the registry (#10745) * refactor(browser): read every CDP event payload through the registry Register Target.attachedToTarget, Target.detachedFromTarget, Page.lifecycleEvent and WebMCP.toolsAdded/toolsRemoved, and carry a requested navigation's reason and a commit's transition type in the frame-event payload. The timeline no longer threads raw params into its entries: each entry receives its timestamp, frame and loader identity explicitly. WebMCP discovery, the service-worker policy blocker and the target-event matcher read the registered payload. With no raw reads left, the cdp-raw-event-params guard is enforced at zero instead of counted. * refactor(browser): drop raw payload helpers the timeline and worker blocker no longer use * refactor(browser): type Playwright CDP session events by the registry (#10751) PlaywrightCdpSession.on subscribes only to registered events and hands the listener the payload parsed by its registered schema, returning the unsubscribe function. Private storage seeding reads registered payloads, including the events of non-flat child sessions, and applies its strict seeding policy to the parsed facts. Its local attach, detach, nested message and pause schemas and the storage-only script/context schemas are removed; Debugger.paused, Runtime.executionContextsCleared and Target.receivedMessageFromTarget join the registry. * test(browser): admit fake policy events through the event registry The service-worker policy now reads event.registered, but the PlaywrightScenarioSession fake connection delivered raw events, so three detached-target tests never reached the policy. The fake now admits each event with receiveCdpEvent as CdpConnection does. * fix(browser): fail the CDP session closed when an event listener throws (#10758) * fix(browser): fail the CDP session closed when an event listener throws An exception from a CDP event subscriber escaped CdpTransportCore's socket message callback uncaught (for example the service-worker blocker's protocol_error on a Target event without a sessionId). The transport now stops delivery, fails the connection as a protocol error whose cause is the listener's exception, rejects pending and later commands with it, and notifies protocol-failure subscribers. The Playwright CDP session relay applies the same rule to its event listeners. * fix(browser): report a failed service-worker policy connection at the next policy check The policy's event listener rejects a malformed Target event, which now fails its connection. With no policy command pending, nothing reported it and later iframe targets went unprotected. The policy records its connection's protocol failure and assertBlocked, run before each scenario step, rethrows it. * fix(browser): keep cleanup commands available after a listener failure A listener failure no longer marks the wire as broken. The transport still rejects pending commands, notifies protocol-failure subscribers, stops delivering events and refuses reuse, but it keeps reading replies and admits commands sent in cleanup grace. The service-worker policy can then remove its init scripts, restore the main realm, detach and release its socket. Wire-level protocol errors still refuse every later command. The PlaywrightScenarioSession policy fake gains onProtocolFailure, which the policy now subscribes to. * refactor(browser): keep raw CDP event payloads out of the received event (#10764) * refactor(browser): keep raw CDP event payloads out of the received event CdpReceivedEvent and CdpTransportEvent no longer carry params: receiveCdpEvent hands the raw payload only to the registered schema, so a subscriber cannot read it by property access, destructuring or computed keys. This supersedes the event.params text guard in architecture-guards, which is removed. * refactor(browser): read registered event payloads in the JavaScript verifiers The runtime, storage and URL-userinfo verifiers subscribe to CdpConnection, which no longer hands subscribers raw params. They now read event.registered. A test scans every scripts/ onEvent callback for raw payload reads, since the TypeScript check does not cover them. The storage verifier's pause trace records a malformed pause instead of the unregistered reason member. * refactor(browser): track the timeline's main frame with the document tracker (#10779) TimelineCapture kept its own mutable main frame id and replaced it on a root replacement. It now holds the CdpDocumentTracker that CdpTargetSession owns and observes the replacement document through it; every main-frame check (lifecycle, navigation, document request, redirect) reads the tracker's current frame. A characterization test pins that the replaced root's lifecycle events are no longer recorded. * refactor(browser): select CDP events only by their registered name (#10829) CdpReceivedEvent carried the wire method as a plain string, so a subscriber could compare it with a misspelt or unregistered name and the check compiled but never matched. Three owners selected Inspector.targetCrashed, an unregistered event, that way. Register Inspector.targetCrashed and drop the wire method from the received event. Subscribers select events by registered.method, whose type is the registered event names. The capture coverage start keeps reading the wire domain, now the event's domain field. * fix(browser): retire a policy child session that CDP reports gone After a listener failure the connection stops delivering events, so an iframe's Target.detachedFromTarget never retires its policy target. Cleanup then sent Page.removeScriptToEvaluateOnNewDocument to the dead session, kept the stale child, and every retry failed before detaching the root. The service-worker policy owner now treats CDP's session-not-found rejection as proof that the child is gone and retires it. The classifier moves from CdpTargetSession to CdpCommandRejection, its owner, and the target-session detach path uses the same one. * refactor(browser): route target events through one session owner (#10835) * refactor(browser): route target events through one session owner Page capture, WebMCP discovery, screenshot capture and the runtime sources each compared the envelope session ID themselves, while the observation window and execution collection used cdpTargetEventMatches, which also routes the root Target.detachedFromTarget that names the target's session. onCdpTargetEvent in CdpTargetEvents.ts now subscribes every target consumer with that one rule; the matcher is private and the per-subscriber comparisons are removed. Electron inspection keeps its own filter while its capture isolation awaits a maintainer decision. * fix(browser): report WebMCP subframe tools whose document is unverified (#10839) * fix(browser): report WebMCP subframe tools whose document is unverified A committed subframe navigation kept the frame's tools silently when CDP reported no loader at the same URL, and removed them on any URL change even when the loader proved the same document. Each frame now carries a CdpDocumentTracker, the session's document identity owner. Only a proven change removes the frame's tools. An unknown comparison keeps them visible, marks webmcp_tools attach-limited and names the frames whose document identity could not be established. * test(browser): prove an unverified live subframe limits WebMCP coverage * fix(browser): key a WebMCP registration by its frame and tool name A subframe tool kept across a committed navigation that changed the URL but not the loader was stored under a key built from the old URL, so a later toolsAdded for the same frame and name added a second entry. Registrations are now keyed by frame and name; tool_key still records the registering frame URL. * test(browser): deliver fake CDP events through the transport's admission (#10840) Event fakes each rebuilt the received event: CdpAgentHints typed its listeners as raw wire events behind an unknown cast, and the Electron, scenario-session and routing tests each wrapped receiveCdpEvent by hand. fakeCdpEvents (tests/fixtures) is a CdpConnection.onEvent fake whose emit admits each raw event with receiveCdpEvent and the wire byte count, so a change to the received event shape fails at the fake instead of silently not exercising subscribers. * refactor(browser): own the selected page generation in one target document tracker (#10860) * refactor(browser): own the selected page generation in one target document tracker Page capture, screenshot, the observation window, the runtime session and the execution window each built a document tracker or rule of their own from root-frame navigation events. CdpTargetDocument now follows the target session's root-frame events and the frame-tree replies its consumers read, classifies root identity once, and reports each navigation to consumers that decide only what it means for their evidence. * fix(browser): report a lost scenario policy connection before the next step (#10864) * fix(browser): report a lost scenario policy connection before the next step The service-worker policy recorded only protocol failures. When its CDP socket closed or its page session detached, later documents lost the blocking script, but the scenario learned of it only when a frame check found an unprotected realm. The owner now records the disconnect or detach when CDP reports it; the next policy check and the next step's action report it first. * fix(browser): refuse an unregistered CDP command before it reaches the browser (#10868) JavaScript verifiers can name any command, and the send owners refused an unregistered one only when its reply arrived, after the browser had acted on it. CdpConnection and the Playwright session now refuse the name before sending, and the Playwright session refuses an unregistered event name instead of subscribing to events no listener receives. The verifier text scan stays as an early warning and documents what it cannot see. * fix(browser): keep a proven root change and the loaderless selection's uncertainty Two review findings on the target document owner. A root event naming another frame with a malformed loader set `changed` but was announced as unidentified, so the execution window failed with protocol_error and dropped what it had collected; the owner now announces it as the proven change it is. The runtime session compared each frame-tree reply with the tracker's current document, which can learn a loader from an event, so a loaderless selection followed by an event and a reply with that loader compared as same; it now compares the reply with the selected document through the owner, and reports target_changed as before. * test(browser): refuse the next scenario step after the policy session detaches * refactor(browser): read WebMCP document identity from the target document owner (#10884) * refactor(browser): read WebMCP document identity from the target document owner WebMCP discovery compared the first and last frame-tree roots itself and kept a document tracker per subframe. CdpTargetDocument now follows the selected root and each committed subframe for it: the final frame tree feeds the owner, a root change proven by a navigation event during discovery is target_changed as in page capture, and a subframe whose committed document changed loses its tools. A subframe navigation without a loader still keeps the tools and reports them as unverified. * fix(browser): start a subframe first seen within its document with an unknown loader A subframe absent from the initial frame tree and first seen through Page.navigatedWithinDocument had no document tracker, so a later commit started a fresh one and the tools it registered meanwhile lost the unverified-document limitation. The owner now starts such a subframe with an unknown loader. * fix(browser): refuse a verifier's unregistered CDP event name at subscription (#10885) JavaScript verifiers subscribed to every event with CdpConnection.onEvent and compared registered.method with a string literal. A misspelt or unregistered name never matched and the verifier waited until its timeout. CdpConnection.onRegisteredEvent now takes one event name, refuses an unregistered one before subscribing (the same registry check the Playwright session applies), and hands the listener only that event's registered parse. The verifiers subscribe only through it, and the evaluation test rejects a raw onEvent subscription in scripts. * fix(browser): keep subframe documents by frame and loader without their URLs |
||
|
|
47d14d0fb8 |
refactor(verify): give the javascript verifiers' roots to VerifierFixture (#11068)
* refactor(verify): give the javascript verifiers' roots to VerifierFixture VerifierFixture.retain(reason) keeps a root that an owned command whose cleanup is incomplete may still use, replacing each verifier's local retain flag and cleanup closure. * refactor(verify): give the Ghidra COM, DOS, 6502, NativeAOT and raw verifiers' workspaces to VerifierFixture (#11070) * refactor(verify): give the Ghidra COM, DOS, 6502, NativeAOT and raw verifiers' workspaces to VerifierFixture * refactor(verify): keep the Ghidra decompiler-failure, decompile-timeout and no-return workspaces through VerifierFixture until owned cleanup is verified (#11077) |
||
|
|
4126698407 |
feat(mcp): project compact input schemas into the portable advertised dialect (#10632)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): re-emit advertised patterns in a portable regex grammar * fix(mcp): present discover_tools input through the selected profile The hot-cold catalog registered discover_tools directly with the SDK, so the default compact input profile still advertised its canonical schema, including page-size defaults clients apply on their own (#5322). Route every listed input schema, transport discovery included, through one server-owned presentation, and pass the selected presentation to the deferred server, which serves recorded tool schemas but not discovery. * fix(mcp): keep the Evidence union on described borrowed inputs borrowEvidenceInput installed its advertised projection on one schema instance. A call site's .describe() rebuilds the schema from its definition, so match_native_functions advertised left and right as unconstrained values in every input profile. Install the projection in the borrowed parser's constructor so derived schemas keep it, for both borrowed inputs and borrowed arrays. * fix(mcp): validate advertised dialect by selected profile * fix(mcp): preserve schema widening through references * feat(mcp): project compact input schemas into the portable advertised dialect One projection (advertisedDialectProjection.ts) owns the compact input advertisement: one type per node, items on every array, string literals as enums, oneOf widened to anyOf, allOf merged, tuples as element unions, exclusive bounds made inclusive, and every keyword outside the dialect dropped. Each rewrite is exact or widening; server validation is unchanged. The root description and sentences for dropped cross-field constraints move to the tool description, which Codex and Zed keep. The compact baseline falls to nullable values only (29), which the dialect cannot express without narrowing an input. The gateway shape repairs (typeArrayItemUnions, hasGatewayIncompatibleShape), the second dependentRequired-to-prose copy and the strict-gateway test denylist are removed; the dialect checker gates the inline presentation instead. * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns * fix(mcp): keep projected schemas permissive * fix(mcp): keep references valid when presentation widens their targets * fix(mcp): keep a single union branch's closure scoped to its properties * fix(mcp): keep an allOf member's tuple tail with its own positions * fix(mcp): relax references into negations and conditionals presentation may remove * test(mcp): select the borrowed Evidence contract from its family * fix(mcp): keep astral literals and dynamic references widening in every mode * fix(mcp): omit astral literals and relax untracked references when presentation widens * fix(mcp): read reference pointers by schema position, not segment spelling * fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse * fix(mcp): keep reduced schemas open when their root admits names by pattern * test(mcp): keep the reduced-schema pattern case outside the size-limited block * fix(mcp): omit patterns whose classes name astral characters * fix(mcp): decide union collapse and pointer protection from canonical branches * docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes * fix(mcp): keep prototype-named properties as own properties in the dialect projection * test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe * fix(mcp): protect references into unevaluated keywords lost evaluation removes * fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings * fix(mcp): protect references into literal siblings of relaxed draft-07 references * feat(mcp): omit output schemas from tools/list by default (#10646) * feat(mcp): omit output schemas from tools/list by default No surveyed model API reads an output schema, MCP client validators repeat REA's own result validation, and complete output schemas were about 92% of the default tools/list. REA_MCP_OUTPUT_SCHEMA_PROFILE now resolves to off through one owner (resolveMcpOutputSchemaProfile); compact and full remain selectable. structuredContent is still delivered, and the deferred server serves both off and full from the recorded catalog with the matching recorded identity. Tests and artifact verifiers that validate results against complete advertised output contracts select full explicitly. * fix(mcp): select schemas in verification workflows * fix(mcp): select complete output schemas in the Electron verifier * fix(mcp): select complete output schemas in standalone verifier probes * fix(mcp): select complete output schemas in every verifier transport * test(mcp): select full output schemas in packet and signal schema checks * fix(mcp): validate the doctor probe reply against the canonical output contract (#10655) * fix(mcp): validate the doctor probe reply against the canonical output contract * test(mcp): replay doctor probe validation under every output profile * test(mcp): accept typed-branch nullable unions in the advertised dialect (#10649) * test(mcp): select full output schemas in HTTP session workflows * fix(mcp): keep the Evidence union on described borrowed inputs (#10597) * fix(mcp): keep the Evidence union on described borrowed inputs borrowEvidenceInput installed its advertised projection on one schema instance. A call site's .describe() rebuilds the schema from its definition, so match_native_functions advertised left and right as unconstrained values in every input profile. Install the projection in the borrowed parser's constructor so derived schemas keep it, for both borrowed inputs and borrowed arrays. * test(mcp): select the borrowed Evidence contract from its family * docs(mcp): admit baseline growth only for restored contract declarations * fix(mcp): state reduced multi-type properties as typed branches, not type lists The reduced fallback derived a property's types and emitted them as a type list, which Gemini, Moonshot and Ark reject. A property whose canonical schema is anyOf string and number therefore traded a typed union for a rejected construct when the inline projection fell back. Emit one type, or anyOf typed branches, so [T, null] becomes the dialect's nullable union. |
||
|
|
add15d65b3 |
refactor(verify): give verifier fixture roots one lease on src/process (#10988)
* refactor(verify): give verifier fixture roots one lease on src/process * fix(verify): keep fixture registration closed, carry the lease on the caught failure, share cleanups once |
||
|
|
2caedcfb57 |
refactor(platform): give the host platform one owner and ratchet ambient process.platform reads (#10911)
* refactor(platform): give the host platform one owner and ratchet ambient process.platform reads * refactor(process): pass the host platform to process sampling instead of reading it ambiently #10755 added two process.platform reads (ps selection in process sampling and the desktop build doctor's ps fact) after the host-platform ratchet was measured. The desktop fact already receives the host platform from doctor; process sampling now receives it from the capture harness, removing all five ambient reads there. |
||
|
|
d0fee4e58e |
fix(mcp): re-emit advertised patterns in a portable regex grammar (#10582)
* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): re-emit advertised patterns in a portable regex grammar * fix(mcp): validate advertised dialect by selected profile * fix(mcp): preserve schema widening through references * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns * fix(mcp): keep references valid when presentation widens their targets * fix(mcp): relax references into negations and conditionals presentation may remove * fix(mcp): keep astral literals and dynamic references widening in every mode * fix(mcp): omit astral literals and relax untracked references when presentation widens * fix(mcp): read reference pointers by schema position, not segment spelling * fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse * fix(mcp): omit patterns whose classes name astral characters * fix(mcp): decide union collapse and pointer protection from canonical branches * docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes * test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe * fix(mcp): protect references into unevaluated keywords lost evaluation removes * fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings * fix(mcp): protect references into literal siblings of relaxed draft-07 references |
||
|
|
45881575a6 |
ci(windows): validate advertised MCP schemas in the Windows lane (#10785)
* ci(windows): validate host-absolute path schemas in the Windows lane Windows hosts advertise their own absolute-path pattern (#7151). The lane compiled it through advertisedDialect.test.ts but never validated a Windows path against it. Run absoluteLocalPathSchema.test.ts there, select the lane when the pattern's owner changes, and guard both schema checks in the lane. Refs #10517 * ci(windows): run live MCP schema validity in the Windows lane toolSchemaValidity.test.ts compared the live advertisement with the POSIX-generated .cache/mcp-tool-catalog.json, so it could not run where the Windows lane skips artifact generation. Move the generated-catalog cases into generatedToolCatalog.test.ts, share the reference walkers through the advertised-schema fixture, and add the live-server file to the curated Windows lane and its scope. |
||
|
|
254bb21857 |
refactor(browser): send only CDP commands with registered result schemas (#10666)
* refactor(browser): send only CDP commands with registered result schemas * refactor(browser): open Playwright CDP sessions only through the registered-command owner * fix(browser): keep the restore obligation for an applied override with a malformed reply A schema-rejected success reply means the browser applied the Emulation override, so the attached environment owner records the reset obligation before reporting the protocol error. Only a rejected or unanswered command leaves no obligation. * refactor(browser): open verifier-script CDP sessions through the registered-command owner (#10710) * fix(browser): register the CDP commands JavaScript verifiers send The verifier scripts send Browser.close, Page.createIsolatedWorld, Page.navigate, Page.reload, Target.activateTarget, Target.closeTarget and Target.createTarget through CdpConnection, which now admits every reply through its command's result schema. Register those schemas, refuse an unregistered run-time name as a typed malformed reply instead of a TypeError, and check script send literals against the registry. * fix(browser): keep Target.closeTarget's success member for the verifiers |
||
|
|
8c052bdec5 |
test(architecture): ratchet top-level layer direction and mutual imports (#10584)
* test(architecture): ratchet top-level layer direction and mutual imports Declare a layer for every top-level src/ directory and root source file (domain, contracts, foundation, providers, application, composition, adapters) in scripts/lib/module-layers.mjs. verify:module-boundaries now also builds the production import graph between those units and compares it with a counted baseline: 45 unit pairs import a higher layer (248 imports) and 23 unit pairs import each other. A new upward pair, more imports on a recorded pair, a new mutual import, or an undeclared unit fails; shrinkage is reported so the baseline can be lowered. * fix(architecture): enforce layers for isolated units |
||
|
|
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. |
||
|
|
3e0dc29041 |
fix(browser): type CDP command replies and parse frame trees once (#10604)
* fix(browser): type CDP command replies and parse frame trees once CdpConnection.send is typed by method name. A command registered in src/browser/protocol/CdpCommands.ts has its parameters typed from the protocol table Playwright ships and its reply parsed once by its own result schema; a mismatch rejects that command with CdpMalformedReply (protocol_error, command, JSON pointer) without poisoning the connection. Playwright storage sessions admit replies through the same table. Page.getFrameTree and Page.getResourceTree are the first registered commands. Their one parser keeps per-frame facts tolerant (malformed child entries remain explicit omissions) and replaces the per-site readers: observeMainFrameUrl, mainFrameUrl, walkFrameTrees, frameTreeResources, runtimeFrameTreeSchema and the scenario storage frame schema. A reply without a frame tree used to be retried for two seconds and reported as target_not_allowed; it is now one protocol_error. A guard test counts literal CDP command names without a result schema per source file; the baseline can only shrink. * fix(browser): consume parsed CDP facts across boundaries |
||
|
|
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 |
||
|
|
e53212655b |
refactor(contracts): derive the public tool catalog from one contract-group list (#10564)
* refactor(contracts): derive the public tool catalog from one contract-group list toolContracts.ts and toolFamilies.ts each imported and listed the same contract groups. toolContracts.ts now owns one ordered group object; TOOL_CONTRACTS is its flattened values in the same catalog order, and toolFamilies.ts reads TOOL_CONTRACT_GROUPS from it instead of re-importing every group. The static catalog-source lint rule learns the Object.values(groups).flat() composition so positional-contract enforcement still discovers every group without executing modules. * fix(lint): reject computed tool catalog groups |
||
|
|
30d23ccd92 |
fix(verifiers): accept Hopper's declared unknown relationship coverage
verify-real-hopper asserted complete relationship coverage for analyze_function, but HopperProvider always declares unknown caller and callee coverage with a reason, and compare_functions then reports the calls dimension as unknown. The fixture oracle now checks the declared unknown and its reason instead of demanding coverage Hopper never claims. Fixes #8067 Only the verifier hunk of #9496 is taken; the rest of that PR reverted unrelated main code. Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com> |
||
|
|
0b21b6ce03 |
fix(skill): keep recovery client IDs aligned with the setup registry
The registration repair guide named 24 of the 29 client IDs that `rea setup --client` accepts. Add codebuddy, cline, kimi, workbuddy and lm_studio, and make the documentation-facts check require every setup client ID in that list so a new client cannot be omitted again. Regenerate the tracked Cursor plugin copy of the reference. Fixes #7640 Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com> |
||
|
|
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. |
||
|
|
67ce671d66 |
fix(verifiers): release fixture roots only after their owners finish (#10491)
* fix(verifiers): release fixture roots only after their owners finish Several real-tool verifiers released a fixture root even when a cleanup that still used it had failed, so a surviving MCP server, session or descendant kept running against a deleted directory and the failure looked like ordinary cleanup. - scripts/lib/verifier-cleanup.mjs: new releaseAfter(dependents, release, retained) task. It attempts every dependent cleanup and releases the resource only if all succeed; otherwise it keeps the resource and reports it with the dependent failures. - verify-signal-recording: the root is released after the MCP client and transport close, and the host-limits read moves before the root is acquired so its failure cannot leak the root. - verify-recorded-crash: sessions, the sentinel and the process-lineage check must all succeed before the root is released. A transport close failure after a failed connect keeps the connect failure. - verify-wasm-artifact: both roots are released after the MCP client and transport close; the residue check and the two directories stay independent after that. - verify-native-ui: `open -W` exits only after the app exits, so the root is removed only once that exit is observed; otherwise it is retained and reported. Fixes #8561 Fixes #8562 Fixes #8564 Refs #8559 Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(verifiers): treat a signaled open as unproven fixture exit A terminated `open` launcher does not prove the LaunchServices app it started has exited, so only an `open -W` that exits on its own counts. Also clear the grace timer so a prompt exit does not hold the process for the rest of the grace period. Refs #8559 Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(verifiers): model open -W exiting after the fixture is signaled The native UI verifier now removes its root only after `open -W` exits on its own. The authored recording's `open` never exited when the fixture was signaled and had no signalCode, so the complete case waited out the grace period and kept the root. The double now behaves like `open -W`: it exits once the fixture process is signaled. Refs #8559 Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5cddc69c51 | fix(verify): keep adopted resources live until command owner closes (#10314) | ||
|
|
7c9d65fe97 | fix(test): resolve filesystem aliases before planning prerequisites (#10213) | ||
|
|
02ebd3e02d | refactor: prune test-only seams and obsolete helpers (#10275) | ||
|
|
653c49419e | fix(release): validate notes with the publication parser | ||
|
|
5eef239dfd | fix(ci): defer proposals for merged release commits | ||
|
|
ab84ba6839 |
fix(process)!: retain inspection cancellation and cleanup ownership (#10113)
* fix(process): preserve producer-owned inspection cancellation Prototype the explicit inspection origin and retained file/batch owner protocol. Downstream adapter migration and lease binding remain required before integration. * fix(process): type inspection ownership handoffs precisely * fix(process): retain plain inspection preparation cancellation * fix(process): retain explicit inspection cleanup and cancellation facts * fix(process): require explicit inspection facts and cleanup scope * refactor(process): remove redundant cleanup forwarding wrapper * fix(firmware): retain inspection cancellation and cleanup ownership * fix(wakaru): retain typed inspection outcomes and caller scope * fix(ghidra): preserve inspection facts and launch cleanup scope * fix(providers): preserve typed process inspection outcomes * refactor(process): remove obsolete inspection cancellation re-export * fix(native): preserve inspection preparation cleanup and cancellation * fix(registration): retain typed inspection cleanup during Git discovery * fix(process): preserve inspection deadline origin in adapter handoff * fix(process): consume the canonical inspection selector in binding * fix(native): preserve inspection deadlines and cleanup retry completion * test(process): narrow the retained Darwin preparation owner * fix(providers): preserve preparation ownership and timeout policy Narrow preparation facts through their canonical owner, preserve actual cleanup capabilities and recorded cancellation, and keep enclosing command deadlines authoritative. Retain raw inspection records through Java refusal and configuration projections without changing availability fallback policy. * refactor(process): use one inspection failure type owner * fix(providers): retain recorded secondary failures when rebinding * fix(ghidra): preserve normalized inspection facts through public projection * fix(process): normalize native process listing cancellation * docs(development): clarify failure provenance and cleanup verification * fix(process): preserve direct inspection cancellation facts * fix(process): retain inspection owners through termination * fix(process): preserve command inspection cleanup provenance * fix(desktop): preserve inspection facts after cleanup retry * refactor(process)!: migrate desktop capture with inspection producers * fix(desktop)!: preserve capture failure origins and cleanup owners (#10115) * fix(desktop): preserve capture failure origins and cleanup * fix(desktop): type keyring cleanup cancellation * fix(kuna)!: retain copy cleanup before retiring workspaces (#10114) * fix(kuna): own copy cancellation and descriptor cleanup * fix(kuna): close copy descriptors before workspace removal * test(kuna): type copy lifecycle gates for project library * docs(kuna): explain retained copy-file cleanup and staging ownership * docs(kuna): separate cache publication, integrity and cleanup guidance * fix(desktop): retain sampling inspection owners before release * fix(process): preserve capture file read cancellation origin * fix(process): retain capture inspection cancellation and cleanup owners * fix(process): retain sampling inspection failures in capture scope * fix(process): retain inspection failures through mandatory cleanup * fix(process): distinguish sampler shutdown from capture cancellation * fix(browser): retain startup EOF before later cancellation * fix(process): bind capture inspection cleanup to the owning run * test(process): migrate cancellation fixtures to typed owners Record explicit preparation and command cancellation facts, retain exact opaque reasons and physical causes, and guard the mocked version probe from native preparation. Keep the live Wakaru command control while adding a recording equivalent for bounded source verification. * fix(process): own sampling reads and settle inspection peers * fix(errors): retain authored recovery through cleanup composition * fix(process): retain all sampling inspection leaves for final cleanup * test(browser): report recording cleanup signal outcome * fix(process): keep inspection error context out of implicit JSON * fix(desktop): retain normalized sampling cleanup ownership * test(process): assert tagged startup cancellation |
||
|
|
1b36fc2d50 |
fix(scripts): validate package-map ownership and preserve HTML fallback (#10097)
* fix(website): keep the HTML validator when the Markdown route is absent A caller that prefers Markdown gets the HTML probe with its conditional headers deleted, so the Markdown route can be evaluated on its own. When the Markdown sidecar is missing the worker answers with that probe, which never saw the caller's `If-None-Match`, so a matching HTML ETag returned 200 instead of 304. Ask the asset service again with the caller's own request before answering with HTML. The decision moves into `htmlFallback` so the request handler keeps its complexity below the repository bound. Verified by executing `node --test website/worker.test.mjs`: without the change the new case fails with 200 instead of 304, and all four cases pass with it. `oxlint` reports no findings and `oxfmt --check` passes. The website worker test is not part of a CI workflow, so this suite runs locally only. * fix(scripts): resolve package-map imports in the module-boundary guard The guard resolved only relative, absolute and `file:` specifiers, so every `#`-prefixed package-map import returned no target and was skipped. A pure-layer file importing `#javascript-analysis-worker` passed, while the same import written relatively failed with a `pure-layer` diagnostic: the gate failed open on the spelling the package map exists to encourage. Resolve a package-map specifier to the source file that produces its built output, then apply the same ownership rules. The package map is read once per repository root. Verified with the new `scripts/lib/module-boundaries.test.mjs` (2 pass; the package-map case failed before the change) and by running the complete guard on this checkout, which still reports 4138 files with no findings, so the new rule adds no false positive. `oxfmt --check` passes; `oxlint` reports the same single pre-existing `failedBoundary` complexity warning it reported before this change. The script tests are not part of a CI workflow, so this suite runs locally only. * fix(scripts): normalize package targets as file URLs --------- Co-authored-by: 吴佳浩 <wujiahao@supremind.com> |
||
|
|
3ad2e214be |
fix(verifier): retain UF2 workspace until resource cleanup completes (#10096)
* fix(verifier): retain UF2 workspace until resource cleanup completes * fix(verifiers): retain firmware workspace cleanup ownership |
||
|
|
b00138be64 |
fix(verification): retain failed cleanup owners and primary errors (#9993)
* fix(verifiers): retain native cleanup ownership on failure * fix(verification): load cleanup fixtures through the module resolver CodeQL's local threat model treats file contents passed to vm.SourceTextModule as user-controlled code execution. Import the real verifier modules and redirect their dependencies to static mocks instead of compiling script text read from disk. * fix(verifiers): own CLI and MCP process families * fix(verifiers): retire workspaces after cleanup retry --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
83f0a4d238 |
fix(ci)!: verify exact conformance fixture records (#9977)
* fix(ci)!: verify exact conformance fixture records BREAKING CHANGE: Regenerate unversioned conformance manifests with npm run build:fixtures. Schema version 2 separates exact string markers from intentional fragments and rejects the ambiguous strings field. * test(conformance): wait out a cold verifier instead of treating SIGTERM as rejection The compiler-produced complete/REA_C_ENTRY run was killed by its 10s execFile timeout on the loaded source-test runner, with empty stderr and SIGTERM. The stricter record checks already passed locally and for the other compiler-produced cases. Assert the process status and give that cold run room inside the test budget. * fix(ci): preserve carriage returns in nm symbol records nm -j terminates each name with LF. A carriage return before that LF is part of the symbol. Splitting on CR LF dropped it, so a renamed symbol ending in CR matched the name without it. * test(ci): supervise conformance verifier subprocesses --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
4d0f6d9b42 | fix(ci): retain Hopper fixture receipt counts (#9976) | ||
|
|
ea00ca2d46 |
fix(verify): preserve Ghidra oracle state and coverage (#9994)
* fix(verify): check checkpoint state before restoring fixtures * fix(verify): require applicable Ghidra decoder controls * refactor(verify): require explicit instruction fixture facts |
||
|
|
a54e848302 |
feat(cursor): ship a Marketplace plugin with the skill and pinned MCP server (#9878)
Cursor Marketplace installs are Git checkouts, so the plugin manifest points at a synced copy of the authored skill and starts npx -y rea-agents@<release> mcp. Release Please and the release checkpoint keep that pin aligned with the package version. The manifest, skill, and icon checks follow the local plugin bundle contract from #7619, adapted for a checkout that has no dist/. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: GamerDubz <105694977+GamerDubz@users.noreply.github.com> |
||
|
|
4082375e73 |
fix(verifiers): preserve results and own cleanup through completion
Attempt independent resource cleanup without losing primary failures, retain unresolved owners, and publish completion after release. Bound existing producer commands, preserve helper return values, and settle startup and fixture children on failure. Validation: 29 focused boundary tests passed; actual helper-value and import-bound filesystem cleanup controls passed. The real inert-child termination control and targeted JavaScript binding checks passed, alongside typecheck, lint and formatting. Live Ghidra, Cutter, Electron GUI and Windows addon qualification was not run. |
||
|
|
dcee59f273 |
test: strengthen independent oracles and consolidate boundary coverage
Require delivered facts, exact cancellation and malformed-input boundaries, and independent metadata expectations. Transfer unique assertions into stronger keepers before removing duplicate cases and overwritten fixture writes; preserve all consumed core fixture bytes. Validation: 1,190 focused tests passed with 39 platform-dependent skips; 134 composition and conformance tests passed. Typecheck, lint, formatting, discovery and Knip passed. Independent preservation reviews and targeted regression controls passed. |
||
|
|
0c37c22d51 | test: remove copied authentication after command cleanup failure | ||
|
|
a9882a58b2 | test: use a portable producer for HTTP/3 cleanup | ||
|
|
dbfab4a65d |
fix(cli): refuse an unsupported Node.js release before linking (#9297)
* fix(cli): refuse an unsupported Node.js release before linking The dispatcher imported the compiled runtime before checking the runtime range, so a release outside `engines.node` failed while linking a module that imports `createZstdDecompress`. Callers saw a module-linking stack trace from every command, including `--version` and `doctor`, instead of the refusal the installer and `engines` already promise. Check `engines.node` from the package read the dispatcher already performs, before the first compiled import. The helper has no imports of its own: the dispatcher must admit the runtime before any dependency can be resolved. Fixes #9296 * fix(cli): ship and align runtime admission * fix(ci): cover packaged runtime admission helper * test(cli): assert Node admission with structured range results Export satisfiesNodeRange and cover caret, minimum, union, and non-release versions. The dispatcher proves the compiled runtime never loads by the absence of its marker file, and compares stderr to the helper's own message. --------- Co-authored-by: 2SinceJuly <202121119+2SinceJuly@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
25885b05c0 |
feat(v8): inspect V8 code cache containers and retained byte patterns (#8993)
* feat(v8): inspect V8 code cache containers and their retained byte patterns Bytenode-compiled `.jsc` files — the V8 code cache container that `vm.Script`, `vm.compileFunction` and bytenode 2.x write, and that Node single-executable applications and Electron apps ship — had no format-native reader. `inspect_binary_layout` shows the surrounding ELF/PE and `inspect_artifact` inventories the file, but neither decodes the V8 structures, so an agent could not tell which V8 line produced the file, could not learn the container is metadata rather than source, and had nothing to point at a version-pinned decompiler. Issue #8543. `inspect_v8_code_cache` joins the format-native family with `inspect_python_pyc`, `inspect_erlang_beam` and `inspect_kernel_module`: one explicit local file, bounded parsing, no execution, no installation, no child process. **The container is version-dependent, so the reader reports roles with confidence instead of assuming an ABI.** All eight header words are reported with byte offset, observed value, the role this reader believes the word has, and whether that role is `confirmed`, `inferred`, or `unconfirmed`. Only three facts gate admission: the header size this reader pins, the V8 code cache magic high half `0xc0de` (the low half is `ExternalReferenceTable::kSize` and varies per build, so it is a build fingerprint rather than a constant), and a declared payload length that reaches exactly the end of the file. I derived the field semantics from the producer rather than assuming them, and two findings changed the design: - **The word V8 calls the source hash holds the source length on the measured producers.** A 54-code-unit source stored `54`, and sources with the same code-unit length but different content stored the same value, including a source whose UTF-8 length was 154. The reader reports it as `source_length` and the docs say that this name is what the measurement supports, not a claim about what another build stores there. - **`vm.compileFunction` sets a high bit in that word.** The reader masks it out and reports the producer family as `script` or `compile_function`, so the source length stays correct for both producers. Embedded strings are reported as **byte-pattern observations with absolute byte ranges**, labelled as such in the field name and in the limitations. A reported sequence is not proof V8 retained it as a string, and a missing literal is not proof it is absent. **Fail-closed boundaries, all covered by tests:** an unknown magic is a typed `unsupported_target` failure because the file is not a V8 code cache; a short header or a payload-length disagreement is a typed `invalid_request` failure. Neither yields a partial parse and neither records Evidence. Non-goals are explicit in the tool description and the docs: the payload is serialized V8 heap data, not source; recovering logic needs a version-pinned View8-style decompiler that this tool neither provides nor depends on. Fixtures are generated from the running V8 instead of committing a version-pinned binary, so the tests exercise the real producer and stay valid across Node upgrades. - Semantic owner and earliest changed stage: format-native V8 code cache container decoding. - CLI and MCP/tool-catalog contract: one new `artifact-provider` tool and one new `inspect-v8-code-cache` CLI command, registered in `TOOL_CONTRACTS`, the `artifact` language family, `TOOL_EFFECTS`, the capability declarations and services, and the capability inventory. `docs:check` passes, so the generated catalog agrees. - Provider, bridge, target-format, or platform compatibility: no provider runs and no external tool is required, so the tool is available on every supported Node host. - Evidence, artifact, provenance, or reconstruction contract: complete Evidence with the payload byte range as its location; no artifact format, reader, or reconstruction change. - Generated metadata, package, or installation impact: catalog and document facts regenerated by the existing checks; no new dependency. Expected effects: - [x] Target content is returned as bounded structured facts. - `src/v8/V8CodeCacheParser.test.ts` (13 cases): real-producer header facts, per-field role and confidence, source length for both producers, an observation's absolute offset verified against the file bytes, the limitation text, foreign magic, payload-length mismatch, short header, missing payload bytes, a different build constant still admitted, and the observation budget. - `tests/boundary/mcp/v8CodeCacheMcp.test.ts` (4 cases): advertisement and annotations, header facts over MCP, relative-path rejection, unsupported magic, malformed container. - `tests/acceptance/v8CodeCacheCli.test.ts` (4 cases): the public CLI, relative-path resolution, byte-range observations, and the typed failure. - `npx vitest run src/contracts src/v8 src/application/v8CodeCache src/domain/v8` — 242 passed - `npx vitest run tests/boundary/mcp/v8CodeCacheMcp.test.ts tests/acceptance/v8CodeCacheCli.test.ts tests/boundary/filesystem/productCatalog.test.ts tests/acceptance/tools/localToolContracts.test.ts` — 20 passed, 4 skipped - `npx tsc --noEmit -p .` — exit 0 - `npm run build` — exit 0 - `npm run lint` — 0 errors - `npm run knip` — exit 0 - `npm run docs:check` — exit 0 - `npx oxfmt --check src tests docs` — exit 0 Gap: the header table is measured on node v24.22.1 / V8 13.6.233.17-node.58 only. No other V8 build is available here, so a different build's field order is untested; that is exactly why only three facts gate admission and the remaining roles carry a confidence level rather than being asserted. Additive. No existing tool, schema, or behaviour changes. The reader never executes the selected file, never launches a process, and never accesses the network; its audited effects are `mutatesSession: true` only, matching the other static format readers. Human owner: @XiaoBinGan - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue: #8543. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. * chore: retrigger title and readiness checks after the title was corrected * fix(v8): bound the payload scan and use the repository path conventions Review feedback from @greptile-apps on four points. **Bound the synchronous payload scan.** The scan is one synchronous pass over the payload, so the 512 MiB ceiling allowed a single request to hold the process for several seconds. The ceiling is now 64 MiB, matching the pinned CPython pyc reader, and the default is 32 MiB. The scan stays synchronous, like the BEAM and ELF note readers in this family, but the budget that bounds it is no longer large enough to matter. The new `max_file_bytes` ceiling and default are documented. **Use the absolute-path schema.** `path` now uses `absoluteLocalPathStringSchema` instead of `localPathStringSchema`, matching `inspect_erlang_beam`. A relative name previously passed validation and was resolved against the server's working directory, so `module.jsc` could select a different file than the caller meant. The rejection is now at the schema boundary. **State the extraction step.** The handoff in `docs/v8-code-cache.md` now says a cache embedded in a single-executable application or an Electron app must be extracted first, because this reader requires the magic at byte zero and returns `unsupported_target` for the surrounding ELF/PE executable. **Load only the owning contract group in tests.** Both tests now import `V8_CODE_CACHE_TOOL_CONTRACTS` directly instead of resolving the tool through the full catalog, so a focused test no longer constructs every other tool's schema. 21 cases pass across the parser, MCP boundary and CLI acceptance files; `tsc` 0; `build` 0; `knip` 0; `docs:check` 0; `oxfmt --check` 0. * fix(v8): select the tool contract by name in the focused tests Reverts the catalog-position selection I added for a review suggestion. This repository has a lint rule (`rea(no-positional-tool-contract)`) that forbids selecting a tool contract by catalog order, and `toolContract("inspect_v8_code_cache")` is how every neighbouring focused test selects one. The positional form I tried introduced two lint errors, so the named form stays. The review concern was that resolving through the full catalog constructs every other tool's schema. That cost is real but it is the repository's chosen trade: catalog ordering must never select an operation or schema, and `toolContract` is the named accessor that enforces it. * test(v8): cover the new tool in the absolute-path boundary test Main added `tests/boundary/mcp/absoluteLocalPathTools.test.ts` after this branch was opened. It enumerates every tool whose MCP `tools/list` schema must reject a relative path, and `inspect_v8_code_cache` uses `absoluteLocalPathStringSchema`, so the tool belongs in that list. Adding it keeps the enumerated field set complete instead of leaving one absolute-path tool untested. `tests/boundary/mcp` + v8 + contracts: 256 passing. `tsc` 0; `build` 0; `knip` 0; `docs:check` 0; `npm run lint` 0 errors. * perf(v8): read the payload by index instead of allocating per byte `for (const [index, byte] of payload.entries())` allocates a two-element array for every byte of the cache payload. On a 1 MiB payload that allocation dominated the scan. Measured with a real cache built from this parser, alternated so the two forms run against the same input: | payload | entries() | indexed reads | | --- | --- | --- | | 1 MiB | 15.5ms | 4.4ms | That is 3.49x on the scan, and the gap widens on smaller payloads where the allocation cost is a larger share (7.3x at 64 KiB in a synthetic run of the same shape). The scan is the whole cost of `inspect_v8_code_cache` once the file is read, so this is the tool's own hot loop. Output is unchanged: the parser returns one retained string for the 64 KiB fixture, and `src/v8` plus the CLI and MCP boundary files stay at 21 passing. `tsc` 0; `build` 0; `npm run lint` 0 errors. * fix(v8): admit only decimal tokens on the numeric CLI options Main added `tests/boundary/cli/cliDecimalArguments.test.ts` after this branch was opened. It enumerates every numeric CLI option and requires `0x10` and `1e3` to be rejected, because plain `Number` coercion would read them as 16 and 1000. This command's three options forwarded the domain fields unchanged, so the test failed on them: inspect-v8-code-cache options.maxFileBytes: Parser.parse accepts 1e3 inspect-v8-code-cache options.maxStrings: Parser.parse accepts 0x10 inspect-v8-code-cache options.maxStrings: Parser.parse accepts 1e3 inspect-v8-code-cache options.minStringBytes: Parser.parse accepts 0x10 `cliDecimalField` publishes the input view that parses the decimal token first and then lets the domain field own bounds, defaults and help, which is what the other numeric commands use. `tests/boundary/cli/cliDecimalArguments.test.ts` now passes. `tsc` 0; `build` 0; `npm run lint` 0 errors; `knip` 0; `docs:check` 0. * fix(v8): recognize module caches, and advise from remaining headroom Two review findings, each measured on Node 24.22.1 before changing anything. **A module cache was reported as a script.** `vm.SourceTextModule.createCachedData()` sets bit 30 of the source-length word, which the source-length mask `0x1fffffff` leaves out, and the producer check only tested the function bit at bit 29: | producer | source word | | --- | --- | | `vm.Script` | `0x00000013` for a 19-unit source | | `vm.compileFunction` | `0x20000009` for a 9-unit source | | `vm.SourceTextModule` | `0x40000013` for a 19-unit source | So a real module cache was labelled `script`, and `vm.Script` rejects that container. The producer enum gains `module` and the module bit is tested first; the source length is unchanged because both flags sit outside the mask. **The budget advice recommended a retry that could not work.** Both limits have ceilings — `max_strings` at 65536 and `min_string_bytes` at 256 — so an admitted file with more than 65536 runs of 256 bytes reached the branch while every suggested retry was a rejected input. `observationBudgetRemediation` now reads the remaining headroom and only recommends a change that is still admissible, falling back to selecting a smaller artifact when neither can move. The parser message states the fact and leaves recovery to the provider, which is the only place that can see both budgets. `MAX_INSPECT_V8_CODE_CACHE_MIN_STRING_BYTES` names the `min_string_bytes` ceiling that the schema previously spelled inline, so the advice and the schema cannot drift. `docs/v8-code-cache.md` describes both flag bits. `src/v8` plus the CLI and MCP boundary files: 28 passing; 7 new cases fail on the base commit. `tsc` 0; `build` 0; `npm run lint` 0 errors; `knip` 0; `docs:check` 0. * refactor(v8): decide the budget recovery as data, and test the decision The remediation tests matched fragments of the advice sentence and banned old phrases. `docs/testing.md` asks for error codes, recorded limits and recovery behaviour instead of frozen prose, so a harmless reword could fail those tests while wrong advice passed them. `observationBudgetRecovery` now returns the decision — which retries remain within the schema's admitted range, and whether a smaller artifact is the only option — and `observationBudgetRemediation` renders one sentence from it. The tests assert the decision, so the wording is free to change and an incorrect choice cannot pass. This also fixes a bug in the previous shape: it took the `min_string_bytes` branch to mean "lower it", but that branch is reachable with the value already at the schema minimum, where lowering is not a legal retry. The decision now carries `canLowerMinStringBytes` and a `requiresSmallerArtifact` flag for that case. 5 cases, all failing on the base commit, covering both headroom states, either ceiling alone, and the run-length floor. `src/v8` plus the CLI and MCP boundary files: 28 passing. `tsc` 0; `build` 0; `npm run lint` 0 errors; `knip` 0; `docs:check` 0. * ci: rerun after the wakaru release download recovered The only failing job on this branch was `javascript_recovery / real-javascript-recovery`, which failed on `curl: (22) The requested URL returned error: 504` while downloading `wakaru-linux-x64.tar.gz`. The release is reachable again (HTTP 200), so this empty commit re-triggers the lane. * docs(v8): place the guide in the tree and record the feature The guide sat at `docs/v8-code-cache.md`, outside the `docs/guides/` tree every other guide uses, and neither index linked it, so it could not be reached from `docs/README.md` or the VitePress sidebar. Moved to `docs/guides/javascript/`, linked from both indexes, and recorded the feature under `docs/specs/v8-code-cache-inspection/` with `spec.md`, `plan.md` and `tasks.md`. The spec keeps only the premises that were measured on Node 24.22.1 — the three producer words and the retained-string layout — rather than restating the implementation. `npm run docs:check` 0; `npm run format:check` 0; `tsc` 0; `build` 0; `lint` 0 errors; `knip` 0. V8 reader, CLI and MCP files: 28 passing. * docs(v8): use the documented spec path and test the advice against its struct Two review findings. **The records were at `docs/specs/v8-code-cache-inspection/`.** `AGENTS.md:73` asks for `docs/specs/<domain>/<feature-slug>/`, so they move to `docs/specs/v8/code-cache-inspection/`. **The verification section claimed more than the tests do.** It said the producer cases were built from real `vm.Script`, `vm.compileFunction` and `vm.SourceTextModule` output, and that the budget advice was compared with its owning formatter. In fact only `vm.Script` and `vm.compileFunction` are real producers — the module case sets the measured bit on a `vm.Script` cache — and only `observationBudgetRecovery` was asserted. Corrected the claim, and closed the second gap rather than only describing it: `observationBudgetRemediation` now has four cases holding the sentence to the struct it renders from. The sentence must not advise a knob the struct closed, and must mention a smaller artifact exactly when the struct requires one. Verified by making the sentence advise `max_strings` after the ceiling was reached — the test fails. Wording stays free; wrong advice does not. `npm run docs:check` 0; `npm run format:check` 0; `tsc` 0; `build` 0; `lint` 0 errors; `knip` 0. V8 reader, CLI, MCP, absolute-path and decimal-argument files: 34 passing. * fix(v8): restore the absolute-path contract entry after the rebase The rebase onto `main` conflicted in `tests/boundary/mcp/absoluteLocalPathTools.test.ts`: `main` gained `inspect_api_contract`, `inspect_devicetree`, `inspect_playwright_trace` and `inspect_python_pyc` in both the contract list and the path-field map while this branch added `inspect_v8_code_cache`. Both sides are additive, so both are kept. Without the resolution the branch carried conflict markers, which made `mergeable_state` `dirty` and every check on it meaningless. Re-verified after the rebase: `tsc` 0, `build` 0, `format:check` 0, `lint` 0 errors, `knip` 0, `docs:check` 0, and the V8 reader plus its CLI, MCP, absolute-path and decimal-argument boundary files at 34 passing. * test(v8): pin the producer from the runtime's own header word An independent reviewer ran these files on Node 22.23.4, 24.22.1 and 26.12.1. Only 22.23.4 failed, on `separates the compileFunction producer bit from the source length`, expecting `compile_function` and reading `script`. The cause is the fixture, not the parser: `vm.compileFunction(...).cachedData` carries `0x20000009` in the source-length word on Node 24.22.1, with bit 29 set, while Node 22.23.4 does not set that bit at all. Whether a given V8 build marks the word is a build detail, so asserting one build's spelling made the check version-dependent. The case now reads the word the runtime produced and asserts the parser maps it correctly, and keeps the part that must hold everywhere: the source length is the low bits, so it equals both `word & 0x1fffffff` and the source's length. The flag meanings themselves stay pinned by the synthetic `withHeaderWord` cases above, which do not depend on any build. Reverting the parser's `compile_function` arm fails this case and `keeps the function and module flags distinct`. `src/v8` plus the CLI, MCP and absolute-path boundary files: 24 and 34 passing. `tsc` 0; `build` 0; `npm run format:check` 0; `npm run lint` 0 errors; `knip` 0. * fix(v8): report an unflagged producer word as unknown, not as a script `vm.compileFunction` marks bit 29 of the source-length word on Node 24.22.1 (`0x20000004` for a 4-unit source) and does not mark it on Node 22.23.4 (`0x00000004` for the same call). Whether a V8 build marks a function cache is therefore a build detail, and an unflagged word is either a `vm.Script` cache or an unmarked function cache. The container carries nothing that separates the two. The reader reported `script` for that case, which is a confident claim the bytes do not support. My previous commit made the test accept whichever value the runtime produced, which recorded the ambiguity instead of resolving it in the contract. `unknown` is now a producer value, the unflagged word maps to it, and the observed word stays in `header.fields` for a caller that trusts a specific build fingerprint. A limitation line says the same in the report itself. `header.producer` widens to `["script", "compile_function", "module", "unknown"]`; `script` is no longer produced, because no unflagged word can be shown to be one. The spec's producer rule and its verification notes are updated to match. Reverting the mapping to `script` fails 2 of the 24 `src/v8` cases. `src/v8` with the CLI, MCP and absolute-path boundary files: 33 passing. `tsc` 0; `build` 0; `docs:check` 0; `npm run format:check` 0; `npm run lint` 0 errors. `knip` reports one unused export (`builtinDataEffectMethod`) on `main` as well, so it is not from this change. * fix(artifacts): retain completed identity across native parser failures * docs(v8): preserve unknown unflagged cache provenance --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> |
||
|
|
c5ed046d6e |
fix(ghidra)!: qualify memory effect coverage (#8651)
* fix(ghidra): qualify memory effect coverage * fix(native): retain value trace source limitations * fix(native): distinguish value trace policy commitments * fix(ghidra): bind value-flow scope to snapshot profile * test(ghidra): verify legacy value-flow snapshot recovery |
||
|
|
1a0e2c77f2 |
fix(ghidra): qualify selected project call coverage (#8391)
* fix(ghidra): qualify selected project call coverage * test(ghidra): retain verifier MCP cleanup ownership * test(ghidra): document trusted verifier compiler selection * test(ghidra): document owned verifier exit marker * test(ghidra): remove ineffective scan directives * fix(ghidra): supervise project coverage verification * fix(ghidra): supervise verifier compiler process |
||
|
|
f912a68417 |
fix(ghidra): respect Java Unix socket path limits (#8382)
Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
c06b53644b |
fix(ghidra)!: preserve facts in inventory searches (#8376)
* fix(ghidra)!: preserve facts in inventory searches BREAKING CHANGE: Ghidra snapshots made before the search projection profile revision no longer match. Run fresh analysis and save a new snapshot. * test(ghidra): update raw profile digest goldens |
||
|
|
a67525cdf1 |
docs: organize canonical documentation layout and verify new pages (#2791)
* docs: organize canonical documentation layout (URGENTE) Group all existing authored guides by domain and ownership, expose complete navigation, and preserve their public routes. Update physical path consumers and release configuration while retaining historical records. Document domain-based specs and ADR slugs without global numbering. Co-Authored-By: Codex <noreply@openai.com> * fix(docs): honor home layout in all-page route verification * style: format reviewed source changes * fix(docs): preserve routes and navigation cache inputs * fix: repair the static-check failures on the default branch (#2895) * fix: repair the static-check failures on the default branch The default branch fails its own required `Static checks` job three ways, so every pull request reports that job as failed regardless of its own change. - `npm run format:check` reports `src/domain/functionComparison.test.ts` and `src/ida/IdaOperationRunner.ts`. - `npm run lint` reports a duplicate `import { join } from "node:path"` in `tests/boundary/mcp/ghidraInventoryMcp.test.ts` (lines 4 and 17). - `npm run typecheck` reports `format: "devin"` missing from the client format union in `src/application/SupportedClients.ts`, and an unchecked index in `tests/boundary/cli/clientProfileLifecycle.test.ts`, whose pair array is inferred as `string[][]`. Apply the pinned formatter, drop the duplicate import, list the `"devin"` format that its own definition already uses, and mark the pair array `as const`. Validation: `npm run check:fast` and `npm run format:check` pass. * fix(setup): keep Devin on the JSON configuration dialect --------- Co-authored-by: 吴佳浩 <wujiahao@supremind.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> * fix(docs): update links after guide relocation * docs: correct verified documentation route counts * fix(docs): update browser capture guide link after move (#2820) Refresh gettext protected-link comments alongside the authored href. Co-authored-by: Codex <noreply@openai.com> * fix(docs): include http3 lab in stable routes * fix(docs): preserve historical release evidence and links * fix(ghidra): restore Windows verifier identity import * docs(wakaru): preserve pinned upstream policy link * docs(index): retain recently added guide links * docs(mcp): preserve parent retention clarification * fix(cli): preserve standalone import guidance * fix(test): preserve translated guide link drift coverage --------- Co-authored-by: Matheus Breguêz <matbrgz@gmail.com> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: morluto <17176810+morluto@users.noreply.github.com> Co-authored-by: 吴佳浩Alben <35291372+XiaoBinGan@users.noreply.github.com> Co-authored-by: 吴佳浩 <wujiahao@supremind.com> |
||
|
|
4bb53000a3 |
fix(ghidra): clarify function annotation selectors (#8584)
* fix(ghidra): clarify function annotation selectors * test(ghidra): compare catalog guidance with its contract --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
3e8a5f76d0 |
feat(native): retain LLDB source coordinates and verify Pascal calls (#2800)
* feat(native): retain LLDB source coordinates and verify Pascal call entries Preserve partial line-table attribution for native locations and historical evidence compatibility. Verify owned Free Pascal call entries through CLI/MCP. Refs #2382, #2372, #2397 Co-Authored-By: Codex <noreply@openai.com> * docs: namespace native specifications by domain and feature Use stable descriptive paths instead of numeric prefixes to avoid parallel contribution collisions. Co-Authored-By: Codex <noreply@openai.com> * fix(native): bound Pascal verification and compare caller coordinates Address review findings at their producing boundaries and preserve directly affected consumers. Source inspection and git diff --check completed. Tests and automated checks were not run at the user’s explicit request. * fix(native): bound compiler shutdown and source-coordinate fixtures * docs: clarify historical native source verification * fix(native): preserve source attribution and compiler ownership * docs(native): qualify retained source attribution * fix(ci): clean up native Pascal verifier processes * test(native): type the Pascal verifier helper import after merging main Main now typechecks this boundary test, which imports the untyped canonical-temporary-directory helper and reads an unknown catch value. Add the helper's declaration file and narrow the caught error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(native): verify partial source attribution caveat * fix(native): retain verifier compiler cleanup ownership * fix(native): forward verifier cancellation and measure path bytes CLI and MCP artifact runs observe the verifier abort signal, and a failed Pascal verifier test stops the compiler group before deleting its directory. Repeated source locations grow by measured UTF-8 JSON bytes; workflow tokens, CPU and peak memory stay unmeasured. --------- Co-authored-by: Matheus Breguêz <matbrgz@gmail.com> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
1cc979c104 |
feat(ghidra): admit DOS MZ targets on Windows P0 (#7144)
* feat(ghidra): admit DOS MZ targets on Windows P0 Windows Ghidra P0 refused dos-mz although the MzLoader import, 16-bit real-mode language attestation and load-image evidence are host-neutral. Admit dos-mz in inspectWindowsP0TargetSupport and run verify:ghidra:dos on Windows: inherit the system environment there, expect annotation and naming edits to be refused (P0 has no mutation authority), and skip verifier lineage like the 6502 lane. Explicit COM stays refused on Windows; its verifier is built around annotation edits. Refs #7121 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ghidra): check naming refusal in the read-only DOS lane With mutable: false the address-boundary helper skipped every naming request, so the Windows report overstated its coverage. Assert that set_address_name and set_addresses_names are refused with capability_unavailable and leave the entry name unchanged, and declare the optional mutable argument in the .d.mts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ghidra): unwrap failed profile Result before asserting Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix(ghidra): expect an unchanged DOS entry on Windows P0 verification Windows P0 refuses edits, so verifyGhidraAddressBoundaries skips the rename-and-restore and the entry keeps its imported symbol source. The post-check still expected user_defined, which only follows a rename. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0beedcd712 |
perf(mcp): add opt-in hot/cold tool discovery (#9046)
Add per-connection discovery that loads canonical named tools on demand while preserving the default full catalog. Bound discovery replies before changing visibility, preserve family exclusions and Evidence workflows, and reset visibility on HTTP reconnect. Verified with focused protocol tests and real Codex CLI artifact investigations; token costs remain task-dependent, so the profile is opt-in. |
||
|
|
0aaa582977 |
test(ghidra): check retained historical snapshot evidence (#8381)
* test(ghidra): check retained historical snapshot evidence * test(ghidra): select historical observations by address |
||
|
|
15107aa81b | test(ghidra): check structured snapshot profile mismatch (#8536) | ||
|
|
2be2d006b8 | test(ghidra): check regex recovery at its owning boundary (#8578) |