mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(skill): remove obsolete grants and audit tool effects
## Changes Related to #545 and the permission-system removal in #555. - Upgrade the shipped skill to v24 and remove obsolete filesystem grants, per-call approval flags, Electron file-root configuration, and DMG approval flags. Calls follow the user-requested investigation directly. Keep setup plan confirmation, actual OS requirements, and process/archive lifecycle boundaries. - Correct the passive browser guide: endpoint/scope come from requests; ordinary local URL queries are retained, while credentials remain redacted. - Audit canonical tool effects: declare possible DMG process/temp-directory effects, mark fresh extraction non-idempotent, and mark comparisons of supplied captures/PNGs as closed-world. Align artifact-provider capability effects with temporary mount-directory writes. - Retain non-read-only hints for calls that add Evidence to the session; document that annotations are hints and that clients control their confirmation UI. Do not mislabel session mutations as read-only to suppress prompts. - Regenerate package, skill, MCP, and product metadata from source. ## Verification - `npm run test:focused -- <11 affected test files>`: **40 tests passed**, including skill transaction/backup/idempotence, SDK tools/list annotations, actual local capture/PNG comparisons, artifact extraction/containment/cancellation, DMG launcher/cleanup seam, setup confirmation, browser MCP and scenario MCP, CLI catalog parity. - `npm run check`: typecheck, lint, format, knip, package metadata. - `npm run docs:check`: generated catalogs, skill metadata, documentation facts, completion ledger, error schema. No local real Hopper/Ghidra run: their adapters and analysis operations are unchanged. Native macOS DMG behavior is covered locally through the launcher seam; no local macOS/hdiutil claim is made. Real browser verification passed using existing Headless Chrome143.0.7499.4: actual CLI/stdio MCP,9,331,407-byte PNG, passive capture/source maps, and owned/external scenario cleanup. An initial full Chrome143 run failed the existing screenshot-height assertion (1397 versus1536); the dedicated headless-shell run passed the complete verifier without code changes. The verifier run-lineage field remained unavailable; no lineage-coverage claim is made. Browser download into `.codex` was blocked by CDN403, so the successful run used an existing browser without changing host configuration.
This commit is contained in:
1 parent
d19686a2a5
commit
2919def828
18 files changed
+194
-38
No files matched your search
@@ -86,6 +86,20 @@ cleanup behavior; artifact tools carry the input path and requested operation.
|
||||
REA runs the declared request directly and does not infer a broader target or
|
||||
action from it.
|
||||
|
||||
REA does not require permission grants or per-call approval flags. Setup still
|
||||
prints its plan and requires confirmation before changing configuration or
|
||||
installing Hopper. MCP clients control their own confirmation UI.
|
||||
|
||||
Tool annotations describe effects and are hints, not authorization controls
|
||||
([MCP ToolAnnotations](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations)).
|
||||
`readOnlyHint` includes session state: an analysis call that records additive
|
||||
Evidence is marked non-read-only even when it leaves the target unchanged.
|
||||
`destructiveHint` describes possible data loss, not ordinary Evidence recording.
|
||||
Effect metadata covers possible behavior across supported inputs: DMG inventory
|
||||
can launch `hdiutil` and create an owned temporary mount directory; extraction
|
||||
creates a fresh output directory on every call. Comparing supplied web captures
|
||||
or PNG artifacts uses local data without contacting the browser.
|
||||
|
||||
Host requirements remain in force. macOS may deny Accessibility,
|
||||
Screen Recording, or native mounting; provider tools require their selected
|
||||
analysis runtime. These failures are reported at the operation that needs
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"client": "2.0.0",
|
||||
"core": "2.0.0"
|
||||
},
|
||||
"skill_version": "23"
|
||||
"skill_version": "24"
|
||||
},
|
||||
"tools": {
|
||||
"total": 116,
|
||||
@@ -545,9 +545,9 @@
|
||||
"mcp_prompts": 6
|
||||
},
|
||||
"digests": {
|
||||
"tools_sha256": "6974b96ecd0544334571658ce91156eecbac544fd7b7fb7ff92a1d7c1e60e2c9",
|
||||
"tools_sha256": "6b821e70d26368f3e19d405f8ac712855da19d59c90dd2d462d49ff1f9d73eb0",
|
||||
"prompts_sha256": "4762db348821fec787a5b8c6423f2c48a71f6f0ec2afee97b16ad69030ec504b",
|
||||
"combined_sha256": "14d38f650b2d33a0e243f9ee5ecb02b3f2d9e2ba6125e9c3409dd08768e0db1f",
|
||||
"combined_sha256": "bc45ad5ad2c7e1d9b5b11d17c3ea051a33ed04b6ce2ed0cdfd40a95502239d02",
|
||||
"providers_sha256": "2ae8b85b20be338739e500549d275e78e875aaa10235d2ca283f0ade7787da90"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"manifest_id": "ecm_e1e42b22674dbfc40005184c3b934a99bf7ab085fe5f1e0a3f7f091760f918dc",
|
||||
"manifest_id": "ecm_d3116f62b6cd65e63c9fed5c4bc9edd604be7c67fdef1b8f7375fd2c84b85682",
|
||||
"verifier": {
|
||||
"id": "rea-managed-conformance",
|
||||
"version": "1"
|
||||
@@ -13,7 +13,7 @@
|
||||
"skill_digests": [
|
||||
{
|
||||
"skill_id": "reverse-engineer-anything",
|
||||
"sha256": "451efcd0ea11a017ca5417ccf57cc2f3fc5dcc07b71d0e94ba97f2d1757b7de9"
|
||||
"sha256": "11e1170733312681ce2f2d771f1a9ece6c1f0505ef919d122790583857f3094c"
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
name: reverse-engineer-anything
|
||||
description: Reverse engineer native, managed, Electron/JavaScript, packaged, and browser applications with REA. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.
|
||||
metadata:
|
||||
version: "23"
|
||||
version: "24"
|
||||
tool_count: 116
|
||||
catalog_digest: "14d38f650b2d33a0e243f9ee5ecb02b3f2d9e2ba6125e9c3409dd08768e0db1f"
|
||||
catalog_digest: "bc45ad5ad2c7e1d9b5b11d17c3ea051a33ed04b6ce2ed0cdfd40a95502239d02"
|
||||
---
|
||||
|
||||
# REA
|
||||
@@ -53,6 +53,10 @@ Evidence IDs, preserve limitations and incomplete coverage, and never imply
|
||||
that static analysis observed execution. Runtime requests execute the declared
|
||||
target and lifecycle; do not broaden the target or action beyond those fields.
|
||||
|
||||
Within the user's requested investigation, call available analysis tools
|
||||
directly. REA does not require permission grants or per-call approval flags.
|
||||
Follow the declared request scope and the host's actual access requirements.
|
||||
|
||||
## Plan broader investigations
|
||||
|
||||
For requests that span multiple features or subsystems, use a staged workflow:
|
||||
|
||||
@@ -7,8 +7,9 @@ is incomplete or paginated, continue only when the remaining data matters to
|
||||
the task; do not fetch a bundle or resource merely to read a result already
|
||||
returned inline.
|
||||
|
||||
Use `record_unknown` only with explicit approval and name the authority or
|
||||
environment still required. Supply supporting and contradicting evidence IDs.
|
||||
Use `record_unknown` to track unresolved questions in the user's investigation
|
||||
and name the authority or environment still required. Supply supporting and
|
||||
contradicting evidence IDs. It updates the session registry directly.
|
||||
Use `update_unknown` with the current revision; reread after a stale revision
|
||||
instead of retrying blindly. Only qualifying observed evidence can verify a
|
||||
resolution.
|
||||
|
||||
@@ -32,9 +32,11 @@ IDs when using them.
|
||||
Use `extract_artifact` when materialized files are needed. It takes no arguments
|
||||
and materializes all regular files into a fresh temporary directory chosen by
|
||||
REA. Symlinks and encrypted entries are inventory facts, not extractable files.
|
||||
The operation still requires the filesystem-write permission grant; callers do
|
||||
not choose the destination.
|
||||
The result reports the materialized directory; callers do not choose the
|
||||
destination. No separate permission grant is needed.
|
||||
|
||||
Native DMG traversal is macOS-only, read-only, and requires both operator policy
|
||||
and `native_mount_approved: true`; without both, retain the root-hash-only result.
|
||||
Approval for inventory never grants extraction authority.
|
||||
Native DMG traversal automatically uses a read-only mount on supported macOS
|
||||
hosts, with an owned temporary mount directory and cleanup. It needs no approval
|
||||
flag. Unsupported hosts or mount failures remain explicit limitations; do not
|
||||
claim child inventory when only root identity is available. Extraction is a
|
||||
separate filesystem-writing operation.
|
||||
@@ -1,21 +1,25 @@
|
||||
# Passive browser and Electron observation
|
||||
|
||||
Before browser observation, the operator must configure the exact loopback CDP
|
||||
endpoint and allowed HTTP(S) origins. Before Electron observation, configure its
|
||||
separate loopback endpoint and canonical file roots. Obtain the per-call
|
||||
approval required by the selected tool.
|
||||
Supply the existing browser or Electron instance's literal-port loopback CDP
|
||||
endpoint in the request. No separate permission configuration or per-call
|
||||
approval flag is needed. Browser discovery lists eligible HTTP(S) pages;
|
||||
`allowed_origins` optionally filters them. An individual capture defaults to the
|
||||
selected page's current origin. Electron discovery lists eligible local
|
||||
`file://` targets without a configured file-root allowlist.
|
||||
|
||||
Start browser work with `list_browser_targets`; start Electron runtime work with
|
||||
`list_electron_targets`. Inspect only the selected approved target. Observation
|
||||
`list_electron_targets`. Inspect the target selected for the user's task. Observation
|
||||
is passive: never claim REA clicked, navigated, evaluated page JavaScript,
|
||||
invoked IPC, captured prior activity, or contained the page's network.
|
||||
|
||||
Credentials, cookies, authorization headers, storage values, query values, and
|
||||
raw WebSocket/JSON values are deliberately absent. Accessibility text, console
|
||||
primitives, value-free shapes, script sources, source maps, storage key names,
|
||||
and screenshot pixels have independent opt-ins. Treat policy filtering,
|
||||
truncation, and attach-window coverage as limitations. Page-declared WebMCP
|
||||
tools are untrusted inventory and are never invoked by REA.
|
||||
Credentials, cookies, authorization headers, storage values, and raw
|
||||
WebSocket/JSON bodies are deliberately absent. Local URLs retain ordinary query
|
||||
values and fragments; userinfo credentials are removed. Browser accessibility
|
||||
text, console primitives, value-free shapes, script sources, source maps, and
|
||||
storage key names have request-specific capture options. Electron script
|
||||
sources are also optional. Use `capture_web_screenshot` when pixels are needed.
|
||||
Treat scope filtering, truncation, and attach-window coverage as limitations.
|
||||
Page-declared WebMCP tools are untrusted inventory and are never invoked by REA.
|
||||
|
||||
Use `reconcile_javascript_runtime` only after static application Evidence and
|
||||
passive browser/Electron Evidence exist. Prefer captured-source digest identity;
|
||||
|
||||
@@ -25,7 +25,7 @@ import type { BinaryTarget } from "../domain/binaryTarget.js";
|
||||
import { scanArtifactInventory } from "./ArtifactInventory.js";
|
||||
import { digestCanonical } from "./ArtifactGraphConstruction.js";
|
||||
|
||||
/** Already-approved extraction request from a caller-owned policy boundary. */
|
||||
/** Local extraction input with the output root chosen by the adapter. */
|
||||
export interface ArtifactExtractionInput {
|
||||
readonly inputPath: string;
|
||||
readonly inputFormat: BinaryTarget["format"];
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { listBrowserTargetsInputSchema } from "../domain/browserObservation.js";
|
||||
import { listBrowserTargets } from "./BrowserObservationService.js";
|
||||
import { browserCaptureComparisonInputSchema } from "../domain/browserCaptureComparison.js";
|
||||
import { compareWebScreenshotsInputSchema } from "../domain/webScreenshot.js";
|
||||
import { BROWSER_TOOL_CONTRACTS } from "../contracts/browserToolContracts.js";
|
||||
import { CdpBrowserProvider } from "../browser/CdpBrowserProvider.js";
|
||||
import {
|
||||
compareWebCaptureEvidence,
|
||||
compareWebScreenshotEvidence,
|
||||
listBrowserTargets,
|
||||
} from "./BrowserObservationService.js";
|
||||
|
||||
describe("browser observation service prerequisites", () => {
|
||||
it("reports a missing provider without requiring a permission grant", async () => {
|
||||
@@ -21,4 +29,31 @@ describe("browser observation service prerequisites", () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
it("compares supplied scenarios and PNG artifacts without a CDP endpoint", async () => {
|
||||
const browser = new CdpBrowserProvider();
|
||||
const captures = await compareWebCaptureEvidence(
|
||||
browser,
|
||||
browserCaptureComparisonInputSchema.parse(
|
||||
example("compare_web_captures"),
|
||||
),
|
||||
);
|
||||
const screenshots = await compareWebScreenshotEvidence(
|
||||
browser,
|
||||
compareWebScreenshotsInputSchema.parse(
|
||||
example("compare_web_screenshots"),
|
||||
),
|
||||
);
|
||||
for (const result of [captures, screenshots]) {
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) throw result.error;
|
||||
expect(result.value.parameters).not.toHaveProperty("cdp_endpoint");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const example = (name: string) => {
|
||||
const input = BROWSER_TOOL_CONTRACTS.find((tool) => tool.name === name)
|
||||
?.examples[0]?.input;
|
||||
if (input === undefined) throw new Error(`Missing example for ${name}`);
|
||||
return input;
|
||||
};
|
||||
@@ -53,7 +53,10 @@ export class ArtifactProvider implements AnalysisProvider {
|
||||
operation !== "inspect_keyed_archive",
|
||||
mayShowUi: false,
|
||||
mayAccessNetwork: false,
|
||||
mayWriteFilesystem: operation === "extract_artifact",
|
||||
mayWriteFilesystem:
|
||||
operation === "extract_artifact" ||
|
||||
operation === "inspect_artifact" ||
|
||||
operation === "inventory_artifact",
|
||||
changesPermissions: false,
|
||||
requiresRoot: false,
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** Canonical side effects for one caller-visible tool. */
|
||||
/** Possible effects across a tool's supported inputs, including temporary work. */
|
||||
export interface ToolEffects {
|
||||
readonly mutatesTarget: boolean;
|
||||
/** Includes additive Evidence recording, navigation state, and unknown updates. */
|
||||
readonly mutatesSession: boolean;
|
||||
readonly writesFilesystem: boolean;
|
||||
readonly launchesProcess: boolean;
|
||||
@@ -117,8 +118,17 @@ export const TOOL_EFFECTS: Readonly<Record<string, ToolEffects>> = {
|
||||
inspect_plist: nativeEvidence,
|
||||
list_architectures: nativeEvidence,
|
||||
demangle_swift: nativeEvidence,
|
||||
inspect_artifact: evidence,
|
||||
extract_artifact: effects({ mutatesSession: true, writesFilesystem: true }),
|
||||
inspect_artifact: effects({
|
||||
mutatesSession: true,
|
||||
launchesProcess: true,
|
||||
writesFilesystem: true,
|
||||
}),
|
||||
extract_artifact: effects({
|
||||
mutatesSession: true,
|
||||
writesFilesystem: true,
|
||||
launchesProcess: true,
|
||||
idempotent: false,
|
||||
}),
|
||||
decode_interface_builder: evidence,
|
||||
inspect_asset_catalog: nativeEvidence,
|
||||
inspect_keyed_archive: evidence,
|
||||
@@ -134,9 +144,9 @@ export const TOOL_EFFECTS: Readonly<Record<string, ToolEffects>> = {
|
||||
analyze_web_bundle: browserEvidence,
|
||||
observe_web_session: browserEvidence,
|
||||
discover_webmcp_tools: browserEvidence,
|
||||
compare_web_captures: browserEvidence,
|
||||
compare_web_captures: sessionEvidence,
|
||||
capture_web_screenshot: browserEvidence,
|
||||
compare_web_screenshots: browserEvidence,
|
||||
compare_web_screenshots: sessionEvidence,
|
||||
capture_browser_scenario: effects({
|
||||
mutatesTarget: true,
|
||||
mutatesSession: true,
|
||||
|
||||
@@ -30,7 +30,7 @@ interface GeneratedPayload {
|
||||
}
|
||||
|
||||
const GENERATED_PAYLOAD_JSON =
|
||||
'{"auxiliaryProviders":[{"capabilities":[{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inventory_artifact","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inspect_artifact","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"extract_artifact","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":false,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"decode_interface_builder","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":false,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inspect_keyed_archive","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inspect_asset_catalog","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null}],"identity":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"}},{"capabilities":[{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["Availability and textual formats depend on the installed macOS/Xcode toolchain."],"operation":"observe_native_ui","provider":{"id":"native-macos","name":"macOS native inspection utilities","version":null},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":true,"mayShowUi":true,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["Availability and textual formats depend on the installed macOS/Xcode toolchain."],"operation":"capture_native_ui_scenario","provider":{"id":"native-macos","name":"macOS native inspection utilities","version":null},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["Availability and textual formats depend on the installed macOS/Xcode toolchain."],"operation":"inspect_macho","provider":{"id":"native-macos","name":"macOS native inspection utiliLine truncated
|
||||
'{"auxiliaryProviders":[{"capabilities":[{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inventory_artifact","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inspect_artifact","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"extract_artifact","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":false,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"decode_interface_builder","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":false,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inspect_keyed_archive","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.","ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only."],"operation":"inspect_asset_catalog","provider":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"},"reason":null}],"identity":{"id":"rea-artifact-graph","name":"REA safe artifact graph provider","version":"1"}},{"capabilities":[{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["Availability and textual formats depend on the installed macOS/Xcode toolchain."],"operation":"observe_native_ui","provider":{"id":"native-macos","name":"macOS native inspection utilities","version":null},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":true,"mayShowUi":true,"mayWriteFilesystem":true,"mutatesArtifact":false,"requiresRoot":false},"limitations":["Availability and textual formats depend on the installed macOS/Xcode toolchain."],"operation":"capture_native_ui_scenario","provider":{"id":"native-macos","name":"macOS native inspection utilities","version":null},"reason":null},{"available":true,"effects":{"changesPermissions":false,"launchesProcess":true,"mayAccessNetwork":false,"mayShowUi":false,"mayWriteFilesystem":false,"mutatesArtifact":false,"requiresRoot":false},"limitations":["Availability and textual formats depend on the installed macOS/Xcode toolchain."],"operation":"inspect_macho","provider":{"id":"native-macos","name":"macOS native inspection utilitiLine truncated
|
||||
const generatedPayload: unknown = JSON.parse(GENERATED_PAYLOAD_JSON);
|
||||
if (!isGeneratedPayload(generatedPayload))
|
||||
throw new TypeError("Generated MCP catalog payload is invalid");
|
||||
|
||||
@@ -5,5 +5,5 @@ export const PACKAGE_METADATA = {
|
||||
serverSdkVersion: "2.0.0",
|
||||
clientSdkVersion: "2.0.0",
|
||||
coreSdkVersion: "2.0.0",
|
||||
skillVersion: "23",
|
||||
skillVersion: "24",
|
||||
} as const;
|
||||
@@ -16,7 +16,7 @@ interface BrowserScenarioToolRegistration {
|
||||
readonly recordEvidence: BinarySessionPort["recordEvidence"] | undefined;
|
||||
}
|
||||
|
||||
/** Register the controlled browser scenario tool even when policy disables it. */
|
||||
/** Register the browser scenario tool with execution-time provider diagnostics. */
|
||||
export const registerBrowserScenarioTool = (
|
||||
server: McpServer,
|
||||
options: BrowserScenarioToolRegistration,
|
||||
|
||||
@@ -37,7 +37,7 @@ interface BrowserToolContext {
|
||||
readonly progress: ProgressReporter;
|
||||
}
|
||||
|
||||
/** Register browser tools even when policy/provider availability denies execution. */
|
||||
/** Register browser tools with execution-time provider diagnostics. */
|
||||
// oxlint-disable-next-line max-lines-per-function -- direct SDK calls retain each schema-handler type correlation.
|
||||
export const registerBrowserTools = (
|
||||
server: McpServer,
|
||||
|
||||
@@ -17,9 +17,15 @@ describe("canonical skill transaction", () => {
|
||||
".agents/skills/reverse-engineer-anything/SKILL.md",
|
||||
);
|
||||
const sibling = join(home, ".agents/skills/unrelated/SKILL.md");
|
||||
const nativeGuide = join(
|
||||
dirname(destination),
|
||||
"references/native-and-artifacts.md",
|
||||
);
|
||||
await mkdir(dirname(destination), { recursive: true });
|
||||
await mkdir(dirname(nativeGuide), { recursive: true });
|
||||
await mkdir(dirname(sibling), { recursive: true });
|
||||
await writeFile(destination, "stale managed skill\n");
|
||||
await writeFile(nativeGuide, "stale filesystem-write permission grant\n");
|
||||
await writeFile(sibling, "unrelated skill\n");
|
||||
|
||||
expect(await canonicalSkillNeedsInstall(home)).toBe(true);
|
||||
@@ -28,7 +34,34 @@ describe("canonical skill transaction", () => {
|
||||
"stale managed skill\n",
|
||||
);
|
||||
const installedSkill = await readFile(destination, "utf8");
|
||||
expect(installedSkill).toContain('version: "23"');
|
||||
expect(installedSkill).toContain('version: "24"');
|
||||
expect(installedSkill).toContain("call available analysis tools");
|
||||
expect(installedSkill).toContain("obtain approval before setup writes");
|
||||
expect(await readFile(`${nativeGuide}.rea.backup`, "utf8")).toBe(
|
||||
"stale filesystem-write permission grant\n",
|
||||
);
|
||||
for (const reference of [
|
||||
"native-and-artifacts.md",
|
||||
"runtime-observation.md",
|
||||
"evidence-workflows.md",
|
||||
]) {
|
||||
const installed = await readFile(
|
||||
join(dirname(destination), "references", reference),
|
||||
"utf8",
|
||||
);
|
||||
expect(installed).toBe(
|
||||
await readFile(
|
||||
new URL(
|
||||
`../../../skills/reverse-engineer-anything/references/${reference}`,
|
||||
import.meta.url,
|
||||
),
|
||||
"utf8",
|
||||
),
|
||||
);
|
||||
expect(installed).not.toMatch(
|
||||
/filesystem-write permission grant|native_mount_approved|only with explicit approval|Obtain the per-call/u,
|
||||
);
|
||||
}
|
||||
expect(installedSkill).toContain(
|
||||
"use normal repository tools and do not run REA",
|
||||
);
|
||||
|
||||
@@ -75,6 +75,28 @@ describe("tool registration options", () => {
|
||||
annotations: tool.annotations,
|
||||
})),
|
||||
);
|
||||
for (const [name, expected] of [
|
||||
["binary_session", { readOnlyHint: true, openWorldHint: false }],
|
||||
["read_bytes", { readOnlyHint: false, destructiveHint: false }],
|
||||
["set_comment", { readOnlyHint: false }],
|
||||
["unset_bookmark", { destructiveHint: true }],
|
||||
[
|
||||
"capture_process_scenario",
|
||||
{ readOnlyHint: false, openWorldHint: true },
|
||||
],
|
||||
["inspect_artifact", { readOnlyHint: false, openWorldHint: true }],
|
||||
["extract_artifact", { readOnlyHint: false, idempotentHint: false }],
|
||||
["compare_web_captures", { readOnlyHint: false, openWorldHint: false }],
|
||||
[
|
||||
"compare_web_screenshots",
|
||||
{ readOnlyHint: false, openWorldHint: false },
|
||||
],
|
||||
] as const) {
|
||||
expect(
|
||||
advertised.find((tool) => tool.name === name)?.annotations,
|
||||
name,
|
||||
).toMatchObject(expected);
|
||||
}
|
||||
} finally {
|
||||
await Promise.allSettled([client.close(), server.close()]);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js
|
||||
|
||||
import { ArtifactProvider } from "../../../../src/artifacts/ArtifactProvider.js";
|
||||
import { artifactExtractionExecutionSchema } from "../../../../src/contracts/artifactToolContracts.js";
|
||||
import { TOOL_EFFECTS } from "../../../../src/contracts/toolEffects.js";
|
||||
import {
|
||||
artifactExtractionResultSchema,
|
||||
artifactInventoryResultSchema,
|
||||
@@ -14,6 +15,33 @@ import {
|
||||
import type { BinaryTarget } from "../../../../src/domain/binaryTarget.js";
|
||||
|
||||
describe("artifact extraction", () => {
|
||||
it("declares possible native mounts and fresh extraction directories", () => {
|
||||
for (const platform of ["linux", "darwin"] as const) {
|
||||
const provider = new ArtifactProvider(platform);
|
||||
for (const operation of [
|
||||
"inventory_artifact",
|
||||
"inspect_artifact",
|
||||
"extract_artifact",
|
||||
] as const) {
|
||||
expect(
|
||||
provider
|
||||
.capabilities()
|
||||
.find((capability) => capability.operation === operation)?.effects,
|
||||
).toMatchObject({ launchesProcess: true, mayWriteFilesystem: true });
|
||||
}
|
||||
}
|
||||
expect(TOOL_EFFECTS.inspect_artifact).toMatchObject({
|
||||
launchesProcess: true,
|
||||
writesFilesystem: true,
|
||||
mutatesTarget: false,
|
||||
});
|
||||
expect(TOOL_EFFECTS.extract_artifact).toMatchObject({
|
||||
launchesProcess: true,
|
||||
writesFilesystem: true,
|
||||
idempotent: false,
|
||||
mutatesTarget: false,
|
||||
});
|
||||
});
|
||||
it("extracts all regular occurrences through an exclusively owned output tree", async () => {
|
||||
const root = await createTestTempDirectory("rea-extract-");
|
||||
const source = join(root, "source");
|
||||
|
||||
Reference in new issue
Block a user