From f7213a4c080dcc6bb951bbbc1f9be9a6c40e174e Mon Sep 17 00:00:00 2001 From: Edgar Arakelyan Date: Fri, 23 Oct 2026 19:53:42 -0700 Subject: [PATCH] docs(skill): build agent environments from a prompt with request steps and the bundle tool Add the environments reference to the skill and install it with setup: record against a disposable instance, sign in through the UI, write with request steps and read each write back, check coverage, re-record by withheld reason and export the bundle. Route it from SKILL.md, name agent environments in the skill description, and document the request step, the export tool and recording writes. Co-Authored-By: Claude Opus 5.5 --- .../skills/reverse-engineer-anything/SKILL.md | 10 +- .../references/environments.md | 134 ++++++++++++++++++ docs/agent-environments.md | 43 ++++++ docs/browser-scenario-contract.md | 76 +++++++++- .../environment-prompt/plan.md | 21 +++ .../environment-prompt/spec.md | 63 ++++++++ .../environment-prompt/tasks.md | 11 ++ .../scenario-capture/spec.md | 3 +- src/application/SetupSkill.ts | 1 + src/contracts/browserScenarioToolContracts.ts | 2 +- src/generatedPackageMetadata.ts | 2 +- tests/boundary/filesystem/setupSkill.test.ts | 1 + 12 files changed, 360 insertions(+), 7 deletions(-) create mode 100644 .agents/skills/reverse-engineer-anything/references/environments.md create mode 100644 docs/specs/agent-environments/environment-prompt/plan.md create mode 100644 docs/specs/agent-environments/environment-prompt/spec.md create mode 100644 docs/specs/agent-environments/environment-prompt/tasks.md diff --git a/.agents/skills/reverse-engineer-anything/SKILL.md b/.agents/skills/reverse-engineer-anything/SKILL.md index 5c1a6bf9ea..4db8e40151 100644 --- a/.agents/skills/reverse-engineer-anything/SKILL.md +++ b/.agents/skills/reverse-engineer-anything/SKILL.md @@ -1,8 +1,8 @@ --- name: reverse-engineer-anything -description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets 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. +description: Reverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA, and build agent environments (AgentEnv bundles) of web applications from a live instance or a capture. 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: "46" + version: "47" --- # REA @@ -133,6 +133,9 @@ explicit path or endpoint and do not need it. `capture_browser_scenario` with declared actions. See [runtime observation](references/runtime-observation.md) for connect/launch and the focused follow-up browser tools. +- Agent environment (AgentEnv bundle) of a web application: read + [environments](references/environments.md) before recording; it records with + `capture_browser_scenario` and writes the bundle with `export_environment_bundle`. - Fiddler Everywhere traffic or a native `.saz` capture: read the [Fiddler workflow](references/runtime-observation.md#fiddler-everywhere-traffic-debugging). Inspect saved SAZ with `inspect_web_network_capture` and `format: "saz"`; @@ -447,6 +450,9 @@ as complete while required questions remain open. [references/runtime-observation.md](references/runtime-observation.md) - Evidence paging, comparisons, residual unknowns, and verification: [references/evidence-workflows.md](references/evidence-workflows.md) +- Agent environments (AgentEnv bundles) of a web application, recorded from + a live instance or a HAR: + [references/environments.md](references/environments.md) ## Finish the task diff --git a/.agents/skills/reverse-engineer-anything/references/environments.md b/.agents/skills/reverse-engineer-anything/references/environments.md new file mode 100644 index 0000000000..fa1df8184e --- /dev/null +++ b/.agents/skills/reverse-engineer-anything/references/environments.md @@ -0,0 +1,134 @@ +# Agent environments from a live application + +Use this when the user asks for an agent environment (an AgentEnv bundle) of a +web application: a folder `agent-env` deploys, whose MCP tools answer from what +one recording of the application observed and serve the writes that recording +confirmed. The workflow records the application once with +`capture_browser_scenario`, checks what the environment would serve, records +again if a hint names a gap, then writes the bundle with +`export_environment_bundle`. For a HAR the user already has, skip to +[export](#export-and-hand-off) through `inspect_web_network_capture`, or use +`rea environment-build `. + +## Before recording + +- Record only against an instance the user says is disposable or seeded for + this purpose: every write step creates, edits or deletes its data. If the + user has not said so, ask before any scenario that writes. REA does not + start, seed or reset applications. +- Credentials come from environment variables the user names. Declare each as a + scenario secret, `{secret_id, environment_variable}`; the variable must be set + in the environment REA's MCP server started with. Never ask for a password in + chat. Declared secrets are redacted as the capture records. +- Map the application first with `inspect_web_page` (and `capture_web_screenshot` + when layout matters): the login form's locators, and the API calls behind the + pages that list and edit the entities the user asked about. + +## Record a session an environment can learn writes from + +One `capture_browser_scenario`, launch mode with a Chrome-family +`executable_path`, `start_url` on the application, and +`capture: {network: {request_body: true, response_body: true, header_values: true}}`. + +1. Log in through the UI: `fill` the user and password fields (the password as + a secret reference), `click` submit, then `wait_for` a page element only a + signed-in user sees. +2. Read with `request` steps: each collection the environment needs, twice + before any write, so fields that change on their own show up; one item of + each. +3. Write with `request` steps, two numbered scratch objects per write type, + with varied free text. Read each write back at once, by id and in its list: + +```json +{ + "step_id": "create-folder-1", + "action": "request", + "method": "POST", + "path": "/api/folders", + "json": { "title": "Scratch folder 1" }, + "headers": [ + { + "name": "X-CSRFToken", + "value": { "source": "cookie", "name": "csrftoken" } + } + ], + "expected_status": [200, 201] +} +``` + +- `path` is on the start URL's origin; the page must be on that origin. +- Header values are literals, declared secrets, a cookie the browser holds + (`{source: "cookie", name}`), or a local storage entry + (`{source: "local_storage", key, json_pointer}`), with an optional + `prefix` such as `"Bearer "`. Copy the headers the application's own + requests send (a CSRF header, a bearer token). Values read from the page + are redacted from records made after they are read, not from the login + response that returned them. +- Set `expected_status` on writes, so a refused write fails its step and + the later steps report not having run, instead of recording read-backs of + nothing. + +4. Leave more than a second between a create and its first edit + (`wait_for_timeout` with `duration_ms: 1100`): writes that share a second + with their create can lose their own timestamps. +5. Update both objects and read each back; delete both and read each back + (expect 404) and the list. + +Keep it to about 60 to 160 requests. A scenario with no `request` step is +recorded exactly as before. + +The capture returns its whole Evidence, every recorded body included, which is +often more than a client shows inline. Before checking coverage, confirm that +every entry of `normalized_result.steps` has `status: "completed"`; if the +client saved the result to a file, search it for `"status":"failed"` and read +that step's `error`. A failed sign-in or write cancels every step after it. +Use the result's `evidence_id` for coverage and export; do not paste the +Evidence back into another tool. + +## Check coverage + +`inspect_analysis_view` with the capture's retained evidence id and +`view: {kind: "environment-coverage", template_rules: ["after-uid-literal", +"opaque-token", "sibling-variance", "prefix-variance"]}`. It reports read tools +answered from the state or replayed (`reads.recorded_reasons`), the served write +tools, and each withheld write with its `reason` and `hint`. It does not apply +the serve-time catalog and state size checks; the export reports those. + +Re-record a withheld write at most twice, and only for a recording gap. Stop at +once when the reason is application behaviour, and report the write as +withheld with its hint: + +| Reason | What to do | +| --------------------- | --------------------------------------------------------------------------------------------- | +| `no-state-target` | Re-record: read the collection or item the write changes. | +| `no-observation` | Re-record: read the entity back by id after the write; read it first for an update or delete. | +| `unconfirmed` | Re-record: read the entity and its list after the write. | +| `incomplete-entities` | Re-record: read the entity through every view that lists it. | +| `unexplained-change` | Re-record once with a second, different call of the same write. | +| `no-call` | Re-record once with a write that succeeds. | +| `side-effect` | Stop: the application changes other entities. | +| `contradicted` | Stop: a later read disagrees with the modelled effect. | +| `body-unusable` | Stop: the body is not a JSON object. | + +Use new scratch names on each attempt; the first attempt's objects may still +exist. + +## Export and hand off + +`export_environment_bundle` with `source: {kind: "retained-evidence", +evidence_id}` (or `{kind: "evidence-file", path}`), an absolute +`output_directory` that does not exist yet and whose parent does, and a `name` +(required when the application runs on `localhost` or an IP address). It returns +the coverage again, `tool_count`, the written files and warnings; `dry_run: +true` reports without writing. + +Tell the user how many tools answer from the state, which writes are served and +which are withheld and why, and the run command (`agent-env run `). Say +that the bundle ships the recorded responses and the capture's local path, and +list any `credential-named-members` warning pointers for review. Never publish +or share the bundle yourself. + +See +[agent environments](https://github.com/morluto/rea/blob/main/docs/agent-environments.md) +for what the state, replay and the bundle establish, and +[evidence workflows](evidence-workflows.md) for the manifest and state views. diff --git a/docs/agent-environments.md b/docs/agent-environments.md index 8a7b39d5dc..14c9f339ad 100644 --- a/docs/agent-environments.md +++ b/docs/agent-environments.md @@ -187,6 +187,20 @@ Evidence also records the capture file's absolute path (`subject.local_path`, `parameters.capture_path`, `locations`, `artifact.path`), and the bundle carries it: build from a neutral folder when that path should not ship. +Over MCP, `export_environment_bundle` builds the same bundle and returns the +same report. Its `source` is capture Evidence the session retained +(`{"kind": "retained-evidence", "evidence_id"}`), such as a +`capture_browser_scenario` or `inspect_web_network_capture` result, or a +capture Evidence file (`{"kind": "evidence-file", "path"}`); inspect a HAR with +`inspect_web_network_capture` first. Retained Evidence is written into the +bundle as `--format json` writes it, so the bundle is the one +`environment-build` writes from that file. `output_directory` must be an +absolute path that does not exist yet, whose parent does; the tool creates it +and refuses an existing directory, empty or not. `name`, `template_rules`, +`package_tarball` and `dry_run` work as `--name`, `--template-rule`, +`--package-tarball` and `--dry-run` do, and retained Evidence has no file to +name the environment after, so a loopback or IP origin needs `name`. + ## From a browser scenario The capture can also come from REA itself: a @@ -275,6 +289,35 @@ the replayed body is the bytes the browser exposes for each response, with any declared secret replaced by its redaction marker (a body that redaction had to empty replays no body). +To record writes, sign in through the UI and then send the application's API +calls with [request steps](browser-scenario-contract.md#request-steps): each +sends one request to the start origin through the page's own `fetch`, with the +session's cookies, and a header can carry the CSRF cookie or stored token the +application's own requests send. A write is served only when the capture shows +its effect, so read each collection before writing, read every written entity +back by id and in its list right after the write, and leave more than a second +between a create and its first edit. The environment coverage view names each +write it withholds and what to record next. A scenario with write requests +changes the application's data: record against an instance whose data may +change. + +```json +{ + "step_id": "create-folder-1", + "action": "request", + "method": "POST", + "path": "/api/folders", + "headers": [ + { + "name": "X-CSRFToken", + "value": { "source": "cookie", "name": "csrftoken" } + } + ], + "json": { "title": "Scratch folder 1" }, + "expected_status": [200, 201] +} +``` + ## What a manifest is An environment manifest is a projection of one application's recorded request diff --git a/docs/browser-scenario-contract.md b/docs/browser-scenario-contract.md index 751c133d04..56985a4f3d 100644 --- a/docs/browser-scenario-contract.md +++ b/docs/browser-scenario-contract.md @@ -10,7 +10,8 @@ liveness deadlines. `INPUT_JSON` may be inline JSON or a JSON file path. The minimal request contains only browser launch/connect selection, `start_url`, and at least one `actions` entry. Launch `headless` defaults to `true` and can be set to `false` where the host supports a visible browser. Navigations follow -the destinations named by the scenario and the page's ordinary browser requests; +the destinations named by the scenario and the page's ordinary browser requests, +and [request steps](#request-steps) send only to the start URL's origin; there is no separate origin allowlist or request-interception layer. Environment settings (including service workers blocked by default), empty storage, and a final sanitized URL capture are supplied by default. Set @@ -204,7 +205,8 @@ language environments. HTTP(S) URLs may include ordinary query values and fragments directly. Use ordered structured query entries when a value needs to reference a declared environment-backed secret. Form, storage, and cookie values are either literal -strings or declared secret references. Raw URL userinfo credentials are rejected. +strings or declared secret references; request step headers can also read a +cookie or local storage value from the page. Raw URL userinfo credentials are rejected. Captured credential-header values are not retained, and declared secret values are redacted automatically. A secret may be declared solely to @@ -315,6 +317,76 @@ external browser without closing it. The request itself defines the operation; there is no additional REA grant step. The browser and host still enforce their own access and process rules. +## Request steps + +A `request` step sends one HTTP request from the page with the page's own +`fetch`, so the browser attaches the session's cookies and the request is +recorded in the step's network events like any request the application makes. +Use it to record an application's API, including writes, when driving the UI +for each call would be slower or less exact than calling the endpoint the UI +calls. It is the only action that changes application state without a user +gesture, so run scenarios with write requests only against an instance whose +data you may change. + +```json +{ + "step_id": "create-item", + "action": "request", + "method": "POST", + "path": "/api/items", + "query": [ + { "name": "notify", "value": { "source": "literal", "value": "false" } } + ], + "headers": [ + { + "name": "X-CSRFToken", + "value": { "source": "cookie", "name": "csrftoken" } + }, + { + "name": "Authorization", + "value": { + "source": "local_storage", + "key": "auth", + "json_pointer": "/token" + }, + "prefix": "Bearer " + } + ], + "json": { "title": "Scratch item 1" }, + "expected_status": [201], + "timeout_ms": 10000 +} +``` + +- `method` is `GET`, `HEAD`, `POST`, `PUT`, `PATCH` or `DELETE`. `json` is the + body, sent with `Content-Type: application/json` unless a header sets one; a + `GET` or `HEAD` step cannot carry it. +- `path` starts with one `/` and must resolve to the start URL's origin, which + validation checks before the browser starts. When the step runs, the page must + be on that origin; add a `goto` step first if an earlier action left it. + `query` entries are appended in order and may reference declared secrets. +- Header values are literals, declared secrets, a cookie the browser holds for + the request URL (`{"source": "cookie", "name"}`), or a local storage entry on + the start origin (`{"source": "local_storage", "key"}`, with an optional + `json_pointer` into a stored JSON value). `prefix` is sent before the value. + Values read from the page are redacted like declared secrets, as + `[REDACTED:page:.
]`, from records made after the step reads + them; a response recorded earlier, such as the login response that returned + a token, keeps the value. A missing cookie, key or + pointer fails the step. Header names a page's `fetch` cannot set, such as + `Cookie`, `Origin`, `Host` or `Sec-*`, are refused at validation. +- The step completes when the whole response has been read. With + `expected_status`, any other status fails the step and the later actions are + recorded as `cancelled`; without it, any response completes the step. A + network error, or `timeout_ms` passing, fails the step. + +The request runs in the page's main world, so an application that wraps +`fetch` sees it, and it goes through the same network observation as other +page requests: select `network` events and network content to record it. +Captures with request steps state in `limitations` that the steps sent their +declared requests through the page's fetch. A scenario without request steps +is unchanged. + ## Network evidence `capture.events: ["network"]` retains request, response, completion, failure, diff --git a/docs/specs/agent-environments/environment-prompt/plan.md b/docs/specs/agent-environments/environment-prompt/plan.md new file mode 100644 index 0000000000..e25f19d838 --- /dev/null +++ b/docs/specs/agent-environments/environment-prompt/plan.md @@ -0,0 +1,21 @@ +# Plan + +1. Add the `request` action to the scenario schema: methods, path, query, + headers with page value sources, JSON body and expected statuses; validate + the origin and the body against the start URL; include query and header + secrets in the declared-secret check. +2. Add `PlaywrightScenarioRequest.ts`: check the page's origin, build the URL, + resolve header values (admitting values read from the page to the scenario's + redaction), fetch in the page with a timeout and read the whole response, + then check the status. Dispatch it from the action runner with the start + origin, and add the limitation when a scenario has a request step. +3. Add a real-browser lane, `verify:browser:request`: a fixture item API that + requires a CSRF cookie header and a stored bearer token for writes, a write + session recorded through the CLI, the build's served writes, and a failing + expected status. +4. Add the `export_environment_bundle` contract, effects, CLI alias, catalog + family and handler: check the destination as other MCP output tools do, + resolve the capture bytes, and call the build with an exclusive destination. +5. Write the skill reference, route it from SKILL.md and install it with setup. +6. Document the request step, the MCP tool and recording writes. +7. Tests: request step unit tests, the MCP tool boundary, setup's skill files. diff --git a/docs/specs/agent-environments/environment-prompt/spec.md b/docs/specs/agent-environments/environment-prompt/spec.md new file mode 100644 index 0000000000..916940b629 --- /dev/null +++ b/docs/specs/agent-environments/environment-prompt/spec.md @@ -0,0 +1,63 @@ +# Build an environment from a prompt + +## Outcome + +`rea environment-build` builds a bundle from one capture, but an agent asked to +"make an environment of this app" still cannot finish the job through REA's MCP +server. A browser scenario can only reach an application's API through the UI or +a `goto` GET, so recording the writes an environment serves means scripting every +form, and there is no MCP tool that writes a bundle. Nothing tells the agent how +to record a session the state can learn writes from, or when to stop recording. + +A `request` scenario action sends one same-origin request through the page's own +`fetch`, so a scenario can sign in through the UI and then call the application's +API, writes included, with the session's cookies and the CSRF or bearer values +the application's own requests send. An `export_environment_bundle` MCP tool +builds the bundle from capture Evidence, as `environment-build` does. A skill +reference walks an agent from the prompt to a bundle: map, record, check +coverage, re-record by reason, export and hand off. + +## Requirements + +- A `request` step names a method (`GET`, `HEAD`, `POST`, `PUT`, `PATCH`, + `DELETE`), a path on the start URL's origin, ordered query entries, headers, + an optional JSON body and optional expected statuses. Validation refuses a + path that resolves to another origin, a body on `GET` or `HEAD`, and header + names a page's `fetch` cannot set. +- Header values are literals, declared secrets, a cookie the browser holds for + the request URL, or a local storage value on the start origin, optionally + read at a JSON pointer, with an optional prefix. Values read from the page are + redacted like declared secrets from records made after they are read. +- The request runs through the page's `fetch` with same-origin credentials, from + a page on the start origin, and completes when the response is read. A status + outside `expected_status`, a network error or the step timeout fails the step; + later steps are cancelled as for other actions. Its network events are + attributed to the step. +- Captures with request steps say so in a limitation. A scenario without one + validates, runs and records exactly as before. +- `export_environment_bundle` takes retained capture Evidence or a capture + Evidence file, an absolute output directory that does not exist and whose + parent does, and the build's name, template rules, package tarball and dry + run. It writes the bundle `environment-build` writes from the same Evidence + bytes (retained Evidence serialized as `--format json` writes it) and returns + the same report, validated by its output schema. It refuses an existing + directory, empty or not, a parentless or relative one, unknown Evidence, an + unnamed loopback capture and repeated rules, and writes nothing when it + refuses. `environment-build` is its CLI command. +- The skill reference `references/environments.md` is installed with the skill + and routed from SKILL.md. It covers disposable instances only, credentials + from environment variables, the recording rules the state needs, coverage, + the stop rule and the hand-off. +- Stop rule: re-record a withheld write at most twice for a recording gap + (`no-state-target`, `no-observation`, `unconfirmed`, `incomplete-entities`), + once for `unexplained-change` and `no-call`, and stop at once for application + behaviour (`side-effect`, `contradicted`, `body-unusable`). + +## Non-goals + +- No cross-origin requests, form or multipart bodies, or arbitrary script + actions. +- No retroactive redaction of values a request step reads: a login response + recorded before the step keeps the token it returned, as captures do today. +- No application start, seed or reset, and no publishing of bundles. +- No change to what any view derives or any environment serves. diff --git a/docs/specs/agent-environments/environment-prompt/tasks.md b/docs/specs/agent-environments/environment-prompt/tasks.md new file mode 100644 index 0000000000..81f26512a2 --- /dev/null +++ b/docs/specs/agent-environments/environment-prompt/tasks.md @@ -0,0 +1,11 @@ +# Tasks + +- [x] Record the outcome, requirements and non-goals. +- [x] Add the request action, its validation and its Playwright runner. +- [x] Add the real-browser request lane. +- [x] Add the export_environment_bundle tool. +- [x] Write and install the skill reference. +- [x] Document the request step, the tool and recording writes. +- [ ] Run static, formatting, documentation and test gates, and the existing browser lanes. +- [ ] Build environments from prompts with an agent against live applications on Linux VMs. +- [ ] Address the independent review. diff --git a/docs/specs/agent-environments/scenario-capture/spec.md b/docs/specs/agent-environments/scenario-capture/spec.md index 3654d71993..162c401f4f 100644 --- a/docs/specs/agent-environments/scenario-capture/spec.md +++ b/docs/specs/agent-environments/scenario-capture/spec.md @@ -59,7 +59,8 @@ change. - No new browser action: scenarios still cover what the UI requests plus GET reads through `goto`. A fetch or script action would be a new effect and - needs its own scope decision. + needs its own scope decision. (The `request` action was later scoped and + added by [environment-prompt](../environment-prompt/spec.md).) - No change to what the scenario redacts. Values the application returns in response bodies are retained, as they are in HAR captures. - The api-surface view keeps HAR parents only. diff --git a/src/application/SetupSkill.ts b/src/application/SetupSkill.ts index f7f2723b80..2d94e6c83b 100644 --- a/src/application/SetupSkill.ts +++ b/src/application/SetupSkill.ts @@ -30,6 +30,7 @@ export const MANAGED_SKILL_FILES = [ "references/android-applications.md", "references/runtime-observation.md", "references/evidence-workflows.md", + "references/environments.md", ] as const; export const isManagedSkillManifest = (content: string): boolean => diff --git a/src/contracts/browserScenarioToolContracts.ts b/src/contracts/browserScenarioToolContracts.ts index 54bc1bc156..4e19ef730d 100644 --- a/src/contracts/browserScenarioToolContracts.ts +++ b/src/contracts/browserScenarioToolContracts.ts @@ -26,7 +26,7 @@ export const BROWSER_SCENARIO_TOOL_CONTRACTS = [ name: "capture_browser_scenario", ...toolContractMetadata("capture_browser_scenario"), description: - "Run a controlled browser scenario when passive observation cannot exercise the application. Launch the selected executable or connect to a loopback CDP target, provide a start URL and actions, and select storage or artifacts when needed. Environment, empty storage, a URL-only final capture, and measured event-retention budgets are defaults. capture.network selects request_body, response_body, and header_values independently; capture.limits lets callers raise or lower the event count, retained-allocation estimates, network transaction count, and network content budgets. Selected content is returned inline with transaction and event references, byte digests, and explicit unavailable states. Budget omissions identify affected event kinds and network transactions. Credentials and declared secrets are redacted. Agents can run their own local fixture servers to control application responses. Actions run until completion or cancellation unless timeout_ms is set. Results are returned inline.", + "Run a controlled browser scenario when passive observation cannot exercise the application. Launch the selected executable or connect to a loopback CDP target, provide a start URL and actions, and select storage or artifacts when needed. A request action sends one HTTP request to the start origin through the page's own fetch, with header values from secrets, page cookies or local storage; write methods change application state. Environment, empty storage, a URL-only final capture, and measured event-retention budgets are defaults. capture.network selects request_body, response_body, and header_values independently; capture.limits lets callers raise or lower the event count, retained-allocation estimates, network transaction count, and network content budgets. Selected content is returned inline with transaction and event references, byte digests, and explicit unavailable states. Budget omissions identify affected event kinds and network transactions. Credentials and declared secrets are redacted. Agents can run their own local fixture servers to control application responses. Actions run until completion or cancellation unless timeout_ms is set. Results are returned inline.", kind: "browser-provider", inputSchema: browserScenarioInputSchema, outputSchema: evidenceResultOf(browserScenarioCaptureSchema), diff --git a/src/generatedPackageMetadata.ts b/src/generatedPackageMetadata.ts index 871c4a7d57..ed83ae5188 100644 --- a/src/generatedPackageMetadata.ts +++ b/src/generatedPackageMetadata.ts @@ -6,5 +6,5 @@ export const PACKAGE_METADATA = { serverSdkVersion: "2.3.1", clientSdkVersion: "2.3.1", coreSdkVersion: "2.3.1", - skillVersion: "46", + skillVersion: "47", } as const; diff --git a/tests/boundary/filesystem/setupSkill.test.ts b/tests/boundary/filesystem/setupSkill.test.ts index 1ca405548f..dbeb443837 100644 --- a/tests/boundary/filesystem/setupSkill.test.ts +++ b/tests/boundary/filesystem/setupSkill.test.ts @@ -638,6 +638,7 @@ describe("canonical skill transaction", () => { "SKILL.md", "references/android-applications.md", "references/connection-and-recovery.md", + "references/environments.md", "references/evidence-workflows.md", "references/javascript-applications.md", "references/native-and-artifacts.md",