pi-cursor-sdk 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -1
- package/README.md +62 -816
- package/dist/context.js +11 -5
- package/dist/cursor-agents-context.js +6 -6
- package/dist/cursor-api-key.js +1 -1
- package/dist/cursor-bridge-contract.js +1 -13
- package/dist/cursor-cloud-local-state.js +0 -1
- package/dist/cursor-config.js +1 -17
- package/dist/cursor-fallback-models.generated.js +424 -1
- package/dist/cursor-live-run-coordinator.js +1 -0
- package/dist/cursor-local-run-terminal-error.js +57 -0
- package/dist/cursor-mcp-timeout-override.js +6 -17
- package/dist/cursor-native-tool-display-replay.js +5 -5
- package/dist/cursor-native-tools.js +11 -0
- package/dist/cursor-pi-tool-bridge-env.js +25 -2
- package/dist/cursor-pi-tool-bridge-server.js +98 -48
- package/dist/cursor-pi-tool-bridge-snapshot.js +1 -1
- package/dist/cursor-pi-tool-bridge.js +4 -12
- package/dist/cursor-provider-errors.js +0 -6
- package/dist/cursor-provider-live-run-drain.js +8 -3
- package/dist/cursor-provider-overflow.js +7 -21
- package/dist/cursor-provider-turn-finalize.js +2 -0
- package/dist/cursor-provider-turn-prepare.js +8 -1
- package/dist/cursor-provider-turn-runner.js +17 -6
- package/dist/cursor-provider-turn-send.js +3 -0
- package/dist/cursor-provider.js +1 -4
- package/dist/cursor-runtime-state.js +3 -3
- package/dist/cursor-sdk-event-debug.js +2 -2
- package/dist/cursor-sdk-output-filter.js +1 -1
- package/dist/cursor-sdk-process-error-guard.js +1 -2
- package/dist/cursor-session-agent.js +6 -8
- package/dist/cursor-session-scope.js +1 -7
- package/dist/cursor-session-store.js +3 -2
- package/dist/cursor-state.js +9 -23
- package/dist/cursor-tool-lifecycle.js +0 -3
- package/dist/cursor-tool-manifest.js +3 -1
- package/dist/cursor-tool-presentation-registry.js +2 -4
- package/dist/cursor-tool-visibility.js +0 -3
- package/dist/cursor-transcript-tool-specs.js +1 -2
- package/dist/index.js +21 -0
- package/dist/model-discovery.js +0 -1
- package/dist/model-list-cache.js +4 -9
- package/docs/cursor-live-smoke-checklist.md +4 -4
- package/docs/cursor-model-ux-spec.md +18 -8
- package/docs/cursor-native-tool-replay.md +2 -2
- package/docs/cursor-native-tool-visual-audit.md +1 -1
- package/docs/cursor-testing-lessons.md +22 -4
- package/docs/cursor-tool-surfaces.md +32 -3
- package/docs/development.md +101 -0
- package/docs/platform-smoke-implementation.md +3 -2
- package/docs/reference.md +810 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/package.json +1 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/@modelcontextprotocol/core/node_modules/zod/v4/core/versions.js +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/package.json +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/@modelcontextprotocol/server/node_modules/zod/v4/core/versions.js +1 -1
- package/package.json +14 -6
- package/scripts/platform-smoke/artifact-secrets.mjs +13 -4
- package/scripts/platform-smoke/local-resume-runner.mjs +0 -1
- package/scripts/platform-smoke/target-runtime.mjs +4 -2
- package/scripts/platform-smoke/targets.mjs +0 -1
- package/scripts/steering-rpc-smoke.mjs +1 -1
- package/shared/cursor-sdk-output-filter.d.mts +2 -0
- package/shared/cursor-sdk-output-filter.mjs +92 -28
- package/shared/cursor-sensitive-text.d.mts +1 -0
- package/shared/cursor-sensitive-text.mjs +7 -0
- package/src/context.ts +16 -9
- package/src/cursor-agents-context.ts +6 -6
- package/src/cursor-api-key.ts +1 -1
- package/src/cursor-bridge-contract.ts +1 -15
- package/src/cursor-cloud-local-state.ts +0 -2
- package/src/cursor-config.ts +1 -24
- package/src/cursor-fallback-models.generated.ts +424 -1
- package/src/cursor-live-run-coordinator.ts +5 -0
- package/src/cursor-local-run-terminal-error.ts +58 -0
- package/src/cursor-mcp-timeout-override.ts +6 -30
- package/src/cursor-native-tool-display-replay.ts +4 -6
- package/src/cursor-native-tools.ts +14 -0
- package/src/cursor-pi-tool-bridge-env.ts +31 -2
- package/src/cursor-pi-tool-bridge-server.ts +89 -45
- package/src/cursor-pi-tool-bridge-snapshot.ts +0 -1
- package/src/cursor-pi-tool-bridge.ts +2 -18
- package/src/cursor-provider-errors.ts +0 -8
- package/src/cursor-provider-live-run-drain.ts +8 -2
- package/src/cursor-provider-overflow.ts +6 -24
- package/src/cursor-provider-turn-finalize.ts +2 -0
- package/src/cursor-provider-turn-prepare.ts +10 -1
- package/src/cursor-provider-turn-runner.ts +17 -6
- package/src/cursor-provider-turn-send.ts +2 -0
- package/src/cursor-provider.ts +0 -5
- package/src/cursor-runtime-state.ts +3 -3
- package/src/cursor-sdk-event-debug.ts +2 -2
- package/src/cursor-sdk-output-filter.ts +2 -1
- package/src/cursor-sdk-process-error-guard.ts +1 -3
- package/src/cursor-session-agent.ts +8 -8
- package/src/cursor-session-scope.ts +1 -9
- package/src/cursor-session-store.ts +3 -2
- package/src/cursor-state.ts +9 -36
- package/src/cursor-tool-lifecycle.ts +0 -4
- package/src/cursor-tool-manifest.ts +4 -1
- package/src/cursor-tool-presentation-registry.ts +3 -5
- package/src/cursor-tool-visibility.ts +0 -4
- package/src/cursor-transcript-tool-specs.ts +0 -3
- package/src/index.ts +18 -0
- package/src/model-discovery.ts +0 -1
- package/src/model-list-cache.ts +4 -10
|
@@ -8,6 +8,12 @@ This document records maintainer testing lessons for `pi-cursor-sdk`. It complem
|
|
|
8
8
|
|
|
9
9
|
For a **minimal one-session dogfood pass** (baseline env, one native + one bridge call, JSONL ID patterns, bootstrap manifest, edit diff card), use the [Cursor dogfood checklist](./cursor-dogfood-checklist.md) only when its selected changed behavior needs new live proof; do not follow it with a full paid matrix by default.
|
|
10
10
|
|
|
11
|
+
## Durable store identity versus SDK pathname
|
|
12
|
+
|
|
13
|
+
Persisted `storeIdentity.stateRoot` is a durable identity, while the SQLite-open boundary passes `toNamespacedPath(stateRoot)` to the SDK. On Windows, the SDK pathname can therefore have the `\\?\` prefix without changing the stored identity. Native resume tests must compare the SDK value exactly with `toNamespacedPath(handle.storeIdentity.stateRoot)` and verify both existing directories with `realpath`; do not strip arbitrary prefixes or weaken the stable-handle/live-sibling assertions.
|
|
14
|
+
|
|
15
|
+
For native harness diagnostics, set `PI_CURSOR_TEST_EVIDENCE_DIR` before starting the test and use a fresh owned temp directory. Evidence-configured `concurrentFixture` runs retain their original fixture roots and write `fixture-root-*.json` metadata before execution; copied JSONL does not authorize deleting the original JSONL or its ancestors. The targeted macOS/Windows native ownership CI step runs the whole ownership test file, avoiding a name filter that could silently match no cases, and places both original roots and copied evidence under the existing `native-host` artifact directory. Runs without evidence configuration keep their existing teardown behavior.
|
|
16
|
+
|
|
11
17
|
## Core lesson: integration-shaped bugs beat unit mocks
|
|
12
18
|
|
|
13
19
|
The native replay `Tool grep not found` failure was integration-shaped, not unit-shaped:
|
|
@@ -19,11 +25,11 @@ The native replay `Tool grep not found` failure was integration-shaped, not unit
|
|
|
19
25
|
|
|
20
26
|
Passing hundreds of unit tests did not prove that chain was safe. Regression coverage now includes:
|
|
21
27
|
|
|
22
|
-
- `test/index.test.ts` — `before_agent_start` and `turn_start` resync after plan-style strip
|
|
28
|
+
- `test/index-registration.test.ts` — `before_agent_start` and `turn_start` resync after plan-style strip
|
|
23
29
|
- `test/cursor-native-replay-stress.test.ts` — plan strip → resync → grep replay; inactive-tool trace fallbacks
|
|
24
30
|
- `test/cursor-provider-replay-live-run.test.ts` — inactive replay tools emit trace instead of broken `toolUse`
|
|
25
31
|
- `test/cursor-native-replay-trace.test.ts` — shared inactive replay trace formatting
|
|
26
|
-
- `test/cursor-native-replay-routing.test.ts` —
|
|
32
|
+
- `test/cursor-native-replay-routing.test.ts` — disabled-replay disposition, absent-snapshot compatibility, and mixed active/inactive tool partitioning (other disposition behavior is exercised at the provider boundary above)
|
|
27
33
|
- `test/validate-smoke-jsonl.test.ts` — replay scan semantics (real errors vs doc mentions in successful reads)
|
|
28
34
|
|
|
29
35
|
When changing provider/runtime behavior, ask whether the bug spans **pi extension lifecycle**, **active tool state**, **provider streaming**, and **persisted JSONL**. If yes, add an integration-style unit test or live smoke coverage for that chain.
|
|
@@ -50,10 +56,16 @@ If resync runs but `context.tools` is still stale (e.g. only `read` listed), the
|
|
|
50
56
|
|
|
51
57
|
## Stock/transcript provider contract
|
|
52
58
|
|
|
53
|
-
`test/cursor-provider-pi-context.test.ts` drives real `ModelRuntime` / `ModelRegistry` requests into `streamCursor`, with only Cursor SDK execution mocked. Run it against each supported host with all Pi peer imports pinned to that host (including nested native imports); a top-level package version alone is not resolution evidence. Cover official Pi 0.87.1, official latest, and current `fitchmultz/pi` main. The direct development Pi packages are locked 1.0
|
|
59
|
+
`test/cursor-provider-pi-context.test.ts` drives real `ModelRuntime` / `ModelRegistry` requests into `streamCursor`, with only Cursor SDK execution mocked. Run it against each supported host with all Pi peer imports pinned to that host (including nested native imports); a top-level package version alone is not resolution evidence. Cover official Pi 0.87.1, official latest, and current `fitchmultz/pi` main. The direct development Pi packages are locked 1.1.0 snapshots, not qualification targets; resolve latest stable official Pi and current `fitchmultz/pi` main once per workflow run. Their actual nested resolution is recorded with each check, including host TypeBox 1.3.27.
|
|
54
60
|
|
|
55
61
|
The test covers bootstrap/incremental prompts, empty-vs-absent request tools, native replay/drain, cloud fresh/bootstrap selection, and actual host prompt serialization for context files and skills. `test/native-cursor-flow.test.mjs` additionally exercises the compiled extension through the real loader and registered Cursor provider, substituting only the external SDK transport/storage. It verifies actual bridge tool execution, pending-work idle/abort/shutdown/deadline ownership, replay without file access, persisted usage/lineage, tree, compaction, queued steering, abort and reload/disposal. `test/native-cursor-prompt.test.mjs` owns genuine native input, hidden notices, required-budget input, current attachments, custom-only continuation, equivalent conversion, payload/order-changing rejection, and GitHub comment soft guidance across bootstrap/incremental/custom-only sends. `test/native-cursor-ownership.test.mjs` owns concurrent-session contracts, including independently reopened managers for the same file, pending bridge survival across sibling reload/tree/shutdown, durable-key stability and atomic live-handle exclusion. These owners use `test/helpers/native-cursor-harness.mjs` and run in the explicit `check:compat` list and manual official-host compatibility route; the native-platform Vitest job is not execution evidence for these Node test owners. Explicit `tools` is now an allowlist, not merely an initial active set; use `defaultTools` for a native fixture that allows replay wrappers to activate. `test/native-provider.test.mjs` additionally verifies canonical `SessionManager.appendContextEdit()` plus `refreshContext()`, unchanged raw history, and conversation filtering that preserves system instructions, the current tool declaration, and explicit tool removal (the focused native slice from #271). It is offline contract evidence. Add live proof only for changed behavior that still needs real-service evidence under the cost policy above; do not rerun unchanged live lanes or infer full live coverage from offline tests.
|
|
56
62
|
|
|
63
|
+
### Native auth/catalog fixture boundary
|
|
64
|
+
|
|
65
|
+
`test/cursor-native-auth-catalog.test.ts` uses public `ModelRuntime.create({ modelsPath: null })` for cases that do not exercise configuration files. Credentials and the Cursor catalog cache remain real; config-precedence and config-edit cases still use a temporary `models.json`. Seed startup credentials and the matching cache before creating the runtime.
|
|
66
|
+
|
|
67
|
+
Official Pi 1.1.0 retains the [file-backed startup refresh-admission/readiness limitation](./cursor-model-ux-spec.md#source-of-truth): registration starts an unawaited refresh, and an asynchronous config load can supersede the awaited session refresh before its catalog publishes. This can return the bundled fallback despite an authenticated matching cache, including when auth/cache were seeded before runtime creation. The in-memory fixture isolates Cursor auth/publication assertions from that shared host defect; it does **not** qualify or repair official file-backed startup. The shared-owner repair in `fitchmultz/pi` [#190](https://github.com/fitchmultz/pi/pull/190) admits refresh ownership before config I/O and awaits replacement publication. File-backed startup proof must use that repaired host and retain its exact revision.
|
|
68
|
+
|
|
57
69
|
## Installed SDK vs native host evidence
|
|
58
70
|
|
|
59
71
|
The native harness substitutes external Cursor SDK transport/storage. It qualifies Pi ownership, scheduling and persisted-session behavior, not real SDK request-time linking. `test/cursor-sdk-lazy-import.test.ts` separately drives public installed `Agent.create()` → `send()` → `run.wait()` with `JsonlLocalAgentStore`, an empty credential environment/private HOME, and pre-import Node network/process guards. The positive case reaches exactly one blocked key-exchange fetch; the negative case denies an SDK module only after creation and fails before network. This protects first-send linking beyond a successful static import. The guards are public Node API interception, not an OS sandbox, and neither case qualifies authenticated gRPC, compiled Pi or the original Windows embedded hosts.
|
|
@@ -72,6 +84,12 @@ SDK 1.0.37 does materially change its vendored transport/retry source: HTTP/2 pi
|
|
|
72
84
|
|
|
73
85
|
The 60-second MCP protocol default and lack of a public timeout option remain. SDK 1.0.37's internal `setToolCallRequestOptions`, `setToolCallOutputSchemaPassthrough` and `setListingDeadline` each occur only as definitions in the inspected ESM JavaScript, with no invocation found. They are not supported public setters or proof of readiness; preserve the extension's verified timeout compatibility path rather than adding private patches. The new public `computerUse` output variant uses the existing bounded generic replay fallback, not dedicated action/screenshot rendering or a new local execution option; see the [canonical replay matrix](./cursor-native-tool-replay.md#sdk-tooltype-replay-matrix).
|
|
74
86
|
|
|
87
|
+
### SDK 1.0.40 hook maintenance boundary
|
|
88
|
+
|
|
89
|
+
The 1.0.40 pin has a concrete compatibility/security reason beyond its version number. Both 1.0.37 and 1.0.40 load enabled Claude user/project hook settings, but only 1.0.40 enables nested `hookSpecificOutput` compatibility in the LOCAL hook runtime factory. A successful command hook returning only nested `permissionDecision: "deny"` or `updatedInput` otherwise leaves the top-level fields consumed by the adapters absent. SDK 1.0.40 also adds Windows native exit-code propagation and UTF-8 payload handling; exit 2 denotes denial, while other nonzero exits normally require `failClosed` to block.
|
|
90
|
+
|
|
91
|
+
`test/cursor-sdk-hook-compatibility-contract.test.ts` reuses the installed-module harness to discover that factory structurally, observe its lexical binding in a test-only evaluation, load fresh project Claude settings, and execute a harmless Node hook child. It checks nested denial/rewrite, output precedence/event guards, UTF-8 stdin and native exit-2 handling. Original fixtures are retained when `PI_CURSOR_TEST_EVIDENCE_DIR` is set. Linux results do not qualify Windows PowerShell; the unchanged native Windows CI runs this contract too. The rewritten command is not executed, and neither a public Agent/model request nor Pi/rtk policy enforcement is tested. These checks do not close #173 or qualify #206/#233/#247/#257/#282/#339; SDK 1.0.40 still exposes neither commit nor PR attribution control (#302). Preserve all earlier package/canary/catalog observations at their actual versions and dates.
|
|
92
|
+
|
|
75
93
|
## Maintainer-only offline proof retention
|
|
76
94
|
|
|
77
95
|
Native SQLite fixtures should open the public `SqliteLocalAgentStore` from `@cursor/sdk/sqlite` with an explicit `stateRoot` under their temporary directory, pass it as `localStore` to `createAgentPlatform`, and await `dispose()` in `finally` before removing that directory. `scopedWorkspaceRef` filters agents; it does not relocate storage. Assert the owned `index.db` exists to guard isolation. A fresh missing-agent `checkpointStore.loadLatest()` returning `null` checks the lookup boundary, not per-agent checkpoint database I/O; see `test/cursor-sdk-lazy-import.test.ts`.
|
|
@@ -343,7 +361,7 @@ The script writes timestamped artifacts under `--out` (default `/tmp/pi-cursor-s
|
|
|
343
361
|
|
|
344
362
|
Stdout prints artifact paths and summary counts only. Raw payloads stay on disk and may contain local paths, project text, tool args/results, or secrets — do not commit or share them.
|
|
345
363
|
|
|
346
|
-
Hard repo rule: Cursor SDK behavior claims must come from the installed `@cursor/sdk` package and/or https://cursor.com/docs/sdk/typescript, not from memory or ad-hoc probes alone. Current validation targets Node 24+, exact `@cursor/sdk@1.0.
|
|
364
|
+
Hard repo rule: Cursor SDK behavior claims must come from the installed `@cursor/sdk` package and/or https://cursor.com/docs/sdk/typescript, not from memory or ad-hoc probes alone. Current validation targets Node 24+, exact `@cursor/sdk@1.0.40`, official Pi 0.87.1/latest, and current `fitchmultz/pi` main.
|
|
347
365
|
|
|
348
366
|
## Pi provider SDK event capture
|
|
349
367
|
|
|
@@ -4,9 +4,11 @@ pi-cursor-sdk runs Cursor models through the local `@cursor/sdk` agent runtime b
|
|
|
4
4
|
|
|
5
5
|
## The three surfaces
|
|
6
6
|
|
|
7
|
+
**Version boundary:** the MCP-only opt-out (`PI_CURSOR_NATIVE_TOOLS`) and `/cursor-abort` require **0.5.4 or later**, including [#372](https://github.com/fitchmultz/pi-cursor-sdk/pull/372). Published **0.5.3 ignores the flag and has no such command**. Verify the installed version before relying on these controls; a development version label alone does not prove availability.
|
|
8
|
+
|
|
7
9
|
| Surface | Who owns it | Callable by Cursor? | What pi shows |
|
|
8
10
|
| --- | --- | --- | --- |
|
|
9
|
-
| **Cursor SDK host tools** | Cursor local agent | Yes | Native replay cards (`read`, `bash`, …) or neutral Cursor activity. Representative ToolType list: [SDK ToolType replay matrix](./cursor-native-tool-replay.md#sdk-tooltype-replay-matrix). |
|
|
11
|
+
| **Cursor SDK host tools** | Cursor local agent | Yes by default; disabled with `PI_CURSOR_NATIVE_TOOLS=0` | Native replay cards (`read`, `bash`, …) or neutral Cursor activity. Representative ToolType list: [SDK ToolType replay matrix](./cursor-native-tool-replay.md#sdk-tooltype-replay-matrix). |
|
|
10
12
|
| **Configured Cursor MCP** | Cursor settings / `~/.cursor/mcp.json` | Yes (when loaded) | Neutral **Cursor MCP** activity cards on replay |
|
|
11
13
|
| **Pi bridge (`pi__*`)** | pi-cursor-sdk loopback MCP | Yes, when exposed | Real pi tool names (`cursor_ask_question`, `cursor_activate_skill`, extension tools, …) |
|
|
12
14
|
|
|
@@ -14,6 +16,27 @@ Pi CLI tool toggles apply at the pi tool-registry boundary. `--no-tools`, `--too
|
|
|
14
16
|
|
|
15
17
|
**Not callable:** `cursor-replay-*` IDs in JSONL, pi history tool names used only for display, and transcript labels. Cursor must call exposed `pi__*` MCP names for bridged pi tools, not the pi card name.
|
|
16
18
|
|
|
19
|
+
## Opt-in MCP-only local turns
|
|
20
|
+
|
|
21
|
+
This section requires the supporting installed version described above; the controls are not available in published npm 0.5.3.
|
|
22
|
+
|
|
23
|
+
`PI_CURSOR_NATIVE_TOOLS=0` restricts **ordinary LOCAL** agents through the public SDK `AgentOptions.tools: ["mcp"]`. All other main-agent tools are omitted, including native `task`/subagents (whose own curated toolsets do not inherit a main-loop restriction). Unset, blank, unrecognized, or enabled values preserve the SDK's default toolset. The canonical boolean parser accepts `0`, `false`, `off`, `none`, `no`, and `disabled` as off, and `1`, `true`, `on`, `yes`, and `enabled` as on, case-insensitively with surrounding whitespace ignored.
|
|
24
|
+
|
|
25
|
+
To send file/shell work through Pi's normal execution and `tool_call` hook boundary instead of native Cursor tools:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Verify the installed version supports these controls (0.5.3 ignores the flag).
|
|
29
|
+
PI_CURSOR_NATIVE_TOOLS=0 PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 PI_CURSOR_SETTING_SOURCES=none pi --model cursor/grok-4.6
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The builtin-exposure flag is still required; disabling native tools does **not** silently expose Pi builtins. Pi's active tool registry and hooks still decide which bridged tools are available or blocked. Disabling the bridge as well leaves no Pi tools callable, but does not by itself disable configured Cursor MCP.
|
|
33
|
+
|
|
34
|
+
**MCP-only is not Pi-only or a sandbox.** The SDK `mcp` capability group retains configured Cursor MCP and the Pi bridge. Ambient configured MCP remains unless setting sources are narrowed or disabled (`PI_CURSOR_SETTING_SOURCES=none`). Non-Pi MCP calls do not pass through Pi's `tool_call` hooks. A permitted Pi or MCP tool can itself run a shell, access files/network, or delegate arbitrary work; this is no OS/process security boundary.
|
|
35
|
+
|
|
36
|
+
**Native replay cannot enforce a pre-execution policy.** Native Cursor work runs before its recorded result is replayed into Pi. Pi `tool_call` hooks may block a bridged Pi call before its real `execute()`, but blocking or rewriting native replay cannot prevent or transform the original Cursor command. `PI_CURSOR_NATIVE_TOOL_DISPLAY=0`, `PI_CURSOR_REGISTER_NATIVE_TOOLS=0`, Pi tool toggles, and `PI_CURSOR_PI_TOOL_BRIDGE=0` are not native execution controls. Use the SDK tool-surface opt-out rather than fabricated pre-execution callbacks.
|
|
37
|
+
|
|
38
|
+
The policy is captured before drain/acquisition and forwarded identically to create and resume (SDK tool restrictions are not persisted by Cursor). Opt-out agents have a distinct pooled/durable compatibility identity; defaults retain historical identity bytes. Changing policy replaces the agent at acquisition instead of reusing/resuming one with the opposite policy. Before draining a pending run, the provider checks its captured policy under the drain lease and rejects an opposite-policy continuation without delivering Pi results back to that SDK run. Ordinary mismatch does not cancel the old run: restore the prior policy to finish it, or invoke `/cursor-abort` to release the exact pending local run owned by this session before retrying. This command sends no model turn. If its owned run has an active Cursor Pi turn, it also invokes that turn's public abort before release; it does not abort a non-Cursor Pi turn or release sibling sessions or Cloud agents. Pi's normal abort only signals an active Pi turn; once the mismatch error has fully settled, idle Pi abort cannot reach that older Cursor waiter. Explicit active provider abort still releases its exact scoped pending run even when the signal was aborted before preparation. No recovery path undoes already-executed work. Fresh text-only LOCAL compaction/tree summary agents continue using `tools: []`, independently of this flag. Cloud with explicit native tools disabled fails before SDK creation or lifecycle side effects rather than silently ignoring the control.
|
|
39
|
+
|
|
17
40
|
## Discoverability
|
|
18
41
|
|
|
19
42
|
- **MCP `listTools`** (and pi's MCP catalog when present) lists **MCP servers only** — for example `pi_tools` with `pi__cursor_ask_question`. It does **not** enumerate Cursor SDK host tools such as `Read` or `Shell`.
|
|
@@ -41,7 +64,7 @@ For an advertised-but-unused `pi__subagent`, first identify the active provider/
|
|
|
41
64
|
Default behavior:
|
|
42
65
|
|
|
43
66
|
- Cursor host tools handle files, shell, grep, and edits.
|
|
44
|
-
-
|
|
67
|
+
- Prefer exposed `pi__*` tools for the capabilities described by their current schemas and prompt guidelines, including delegation or MCP work. Use Cursor-configured MCP or Cursor-native subagents only when no matching exposed Pi tool is available; do not assume a particular delegation tool name is registered.
|
|
45
68
|
- The pi bridge exposes **active pi tools** as `pi__*` MCP names when `PI_CURSOR_PI_TOOL_BRIDGE` is enabled (default on).
|
|
46
69
|
- Overlapping pi builtins (`read`, `bash`, `write`, `edit`, `grep`, `find`, `ls`) are **hidden** from the bridge unless `PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1`.
|
|
47
70
|
|
|
@@ -60,10 +83,15 @@ PI_CURSOR_EXPOSE_BUILTIN_TOOLS=1 pi --model cursor/grok-4.6
|
|
|
60
83
|
# Fail a stranded bridge call sooner than the effective MCP tool timeout
|
|
61
84
|
PI_CURSOR_PI_BRIDGE_CALL_TIMEOUT_MS=120000 pi --model cursor/grok-4.6
|
|
62
85
|
|
|
86
|
+
# Announce the bridge URL as localhost and listen on a port or range (for example for a Cursor team MCP allowlist such as http://localhost:800*/mcp).
|
|
87
|
+
PI_CURSOR_PI_TOOL_BRIDGE_HOST=localhost PI_CURSOR_PI_TOOL_BRIDGE_PORT=8000-8009 pi --model cursor/grok-4.6
|
|
88
|
+
|
|
63
89
|
# Disable bootstrap tool manifest
|
|
64
90
|
PI_CURSOR_TOOL_MANIFEST=0 pi --model cursor/grok-4.6
|
|
65
91
|
```
|
|
66
92
|
|
|
93
|
+
For `localhost`, the bridge owns both `127.0.0.1` and `::1` on the selected port before advertising its URL; a conflict on either family skips the port, and missing IPv6 fails closed. The default remains IPv4-only. Host/port settings are captured for the shared server lifetime, not changed under active runs; dispose all its runs before changing them.
|
|
94
|
+
|
|
67
95
|
## Runtime and transport policy
|
|
68
96
|
|
|
69
97
|
Current defaults:
|
|
@@ -82,6 +110,7 @@ Disabling or removing an MCP server **only in pi** does not remove Cursor ambien
|
|
|
82
110
|
| --- | --- |
|
|
83
111
|
| `pi --no-tools` | Disables pi built-in/extension/custom tools and therefore removes pi bridge exposure; Cursor SDK host tools still remain callable. |
|
|
84
112
|
| `pi --tools ...` / `pi --exclude-tools ...` | Narrows pi's active tool registry and therefore the pi bridge snapshot; Cursor SDK host tools and configured Cursor MCP are unchanged. |
|
|
113
|
+
| `PI_CURSOR_NATIVE_TOOLS=0` | Restricts ordinary LOCAL main-agent tools to MCP only, including disabling native task/subagents; Cloud fails closed. Default unchanged. |
|
|
85
114
|
| `PI_CURSOR_SETTING_SOURCES=all` (default) | Loads user/project Cursor MCP, plugins, rules (`~/.cursor/mcp.json`, etc.) |
|
|
86
115
|
| `PI_CURSOR_SETTING_SOURCES=none` | Disables ambient Cursor setting sources for local agents |
|
|
87
116
|
| `PI_CURSOR_SETTING_SOURCES=project,plugins` | Narrows which layers load |
|
|
@@ -100,6 +129,6 @@ Example mistake: treating `cursor-replay-…` as a tool to invoke. Replay never
|
|
|
100
129
|
|
|
101
130
|
## Related docs
|
|
102
131
|
|
|
103
|
-
- [
|
|
132
|
+
- [Reference — Cursor provider tool contract](reference.md#cursor-provider-tool-contract)
|
|
104
133
|
- [Cursor native tool replay](./cursor-native-tool-replay.md)
|
|
105
134
|
- [Cursor model UX spec](./cursor-model-ux-spec.md)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Development and releases
|
|
2
|
+
|
|
3
|
+
Start with the [README](../README.md) for installation and the [Cursor SDK reference](reference.md) for runtime configuration. This page collects maintainer verification, event capture, compatibility and release procedures.
|
|
4
|
+
|
|
5
|
+
## Maintainer cost-conscious verification
|
|
6
|
+
|
|
7
|
+
Run offline/faux tests, native contracts, type checks, builds, and package checks first; preserve offline cross-platform CI. Reuse retained evidence for unchanged tested inputs. Real Cursor calls are only for the smallest meaningful changed-behavior check that needs real-service proof, on one representative environment. Docs/metadata-only changes need no paid testing. Do not replay full paid campaigns, run host matrices merely for matrix coverage, or automatically retry paid failures. Automated Cursor PR reviews continue unchanged.
|
|
8
|
+
|
|
9
|
+
No paid Cursor Cloud testing for generic PRs or releases. Only a PR or issue explicitly focused on Cursor Cloud may use a necessary focused Cloud check; incidental Cloud code changes do not qualify. Cloud product capabilities, offline contracts, and explicit smoke commands remain available. Even for Cloud-focused work, the multi-lane `npm run smoke:cloud` is optional, not an unconditional gate; selected checks retain run/evidence and agent/repository cleanup requirements.
|
|
10
|
+
|
|
11
|
+
[Platform smoke](./platform-smoke.md) documents existing single-suite/single-target commands and the optional comprehensive `npm run smoke:platform:all` matrix. The matrix uses packed installs, PTY/ConPTY ANSI capture, host-rendered xterm/PNG evidence, JSONL assertions, bridge diagnostics, usage/cache checks, abort cleanup, artifact manifests, and redaction scans. `.artifacts/platform-smoke/latest.json` points to each platform run's evidence. Report exactly the scope observed, not unrun matrix coverage.
|
|
12
|
+
|
|
13
|
+
The older live smoke helpers remain useful for inner-loop debugging and focused visual audits, not as the release gate. Use [Cursor live smoke checklist](./cursor-live-smoke-checklist.md), `npm run smoke:visual`, `npm run smoke:live`, or direct `pi --approve -e . --cursor-no-fast --model cursor/grok-4.6` runs only when a changed TUI/card/runtime behavior needs new live evidence. Select one relevant check rather than executing every helper. `npm run smoke:visual` captures an offscreen PTY rendered through browser/xterm and saved as PNG screenshots with Playwright, or with `agent_browser` from the generated HTML when available. Its default matrix is native replay only: native replay registration is forced on, Cursor setting sources are disabled, the pi bridge is off, overlapping built-in pi tools are not exposed, and inherited Cursor SDK event-debug artifact env is cleared; `--event-debug` writes to a deterministic debug directory under the visual output directory. The visible TUI/output, rendered screenshots, scrubbed diagnostics, and persisted JSONL must agree. See [Cursor testing lessons](./cursor-testing-lessons.md) for auth.json seeding, isolated `/tmp` harness layout, JSONL replay-error scans, and other regression traps.
|
|
14
|
+
|
|
15
|
+
## Zod peer and bridge packaging
|
|
16
|
+
|
|
17
|
+
Keep the exact SDK peer `zod@4.6.6` external and the bridge's newer nested `zod@4.6.7` copies bundled. Both contain the upstream bounded-collection fix; their published tarballs differ only in version metadata. This uses npm's ordinary locked dependency layout, not overrides, copied dependencies or SDK patches.
|
|
18
|
+
|
|
19
|
+
Preserve that layout when updating dependencies. Installing the bridge's Zod version at the package root or deduplicating can move the shared copy to the root, where npm includes it in the bridge bundle. Pi's `--legacy-peer-deps` consumer then hoists the unbundled SDK without an accessible Zod peer. `--omit=peer` is not equivalent and does not reproduce that failure.
|
|
20
|
+
|
|
21
|
+
`test/package-metadata.test.ts` owns the required peer/entrypoint contract, SDK v4/v4-mini and bridge parser controls, and the packed-root exclusion guard. For Zod or bundling changes, also pack the built source and install that exact tarball into fresh consumers with default npm, Pi-managed npm (`--legacy-peer-deps --no-audit`), npm `--omit=peer`, Pi-managed pnpm (peer auto-installation off) and Pi-managed Bun (`--omit=peer`). Check actual SDK ESM imports and SDK-relative `zod`, `zod/v3`, `zod/v4`, `zod/v4-mini` resolution, plus the bundled bridge. Retain artifact hashes and installer versions. A clean audit or source-only parser test does not prove the published installation works.
|
|
22
|
+
|
|
23
|
+
## Maintainer Cursor SDK event capture
|
|
24
|
+
|
|
25
|
+
Use `npm run debug:sdk-events` to capture timestamped `run.stream()`, `onDelta`, and `onStep` timelines for one direct `@cursor/sdk` run.
|
|
26
|
+
|
|
27
|
+
Use `npm run debug:provider-events` to capture the same `onDelta`/`onStep` payloads **through pi's Cursor provider** (session agent reuse, bridge, native replay, send planning). Artifacts default under gitignored `.debug/cursor-sdk-events/`. Interactive multi-turn pi sessions group turns under `.debug/cursor-sdk-events/sessions/<session-slug>/turn-NNN-.../` with a `session.json` index. You can also opt in during any pi run with `PI_CURSOR_SDK_EVENT_DEBUG=1`; capture is file-only by default so the pi TUI stays normal. Each cumulative JSONL artifact is capped at 2 MiB, ends with an `artifact_truncated` record when capped, and is listed in `summary.json` under `truncatedJsonlFiles`.
|
|
28
|
+
|
|
29
|
+
See [Cursor testing lessons](./cursor-testing-lessons.md#cursor-sdk-event-capture-probe) for usage, artifact layout, and safety notes.
|
|
30
|
+
|
|
31
|
+
## Automatic npm releases (maintainers)
|
|
32
|
+
|
|
33
|
+
Follow the [shared release procedure](https://github.com/fitchmultz/.github#automatic-npm-releases). When enabled, the `npm release` workflow plans releases on `main` pushes, a daily schedule, and manual dispatch. It runs the existing offline compatibility and native macOS/Windows jobs and qualifies a candidate tarball before publication to npm and GitHub.
|
|
34
|
+
|
|
35
|
+
Before merging, check the final PR head (up to date with `main`) against the [release review gate](../AGENTS.md#release-review-gate-maintainer) and [cost-conscious verification policy](#maintainer-cost-conscious-verification). Complete the exact-release-diff deep review with zero findings, the documented pre-release catalog check, and any genuinely necessary changed-behavior proof. Merging attests genuine satisfaction of existing requirements; it does not create proof. Authenticated checks remain outside CI; automated Cursor PR reviews remain unchanged, and no routine paid Cloud campaigns or paid retries are added. Automated publication disables npm hooks to publish the checked bytes; existing manual publisher instructions remain valid.
|
|
36
|
+
|
|
37
|
+
Before retrying a failed or unpublished candidate, inspect its exact source/run identities and the shared retry procedure. An authentication repair alone does not authorize publishing an old candidate after `main` advances. Never move an existing tag, overwrite its draft/assets, or relabel old proof. The [0.5.1 changelog](../CHANGELOG.md#051-unpublished-source-history) is unpublished source history carried into 0.5.2, not a successful publication record. Set repository variable `NPM_RELEASE_ENABLED` to anything other than `true` to stop new release plans; cancel pending runs separately when needed. Workflow validation is not evidence of a completed real OIDC publication.
|
|
38
|
+
|
|
39
|
+
Publication records are independent: npm published 0.5.2, while GitHub's `v0.5.2` release remains a draft bound to source `9820ae7`. Preserve that tag, draft, and candidate assets unchanged. Verify npm and GitHub records independently for each new release.
|
|
40
|
+
|
|
41
|
+
## Development
|
|
42
|
+
|
|
43
|
+
Required qualification targets are the latest stable official Pi and latest maintained `fitchmultz/pi` main, with optional wildcard Pi/TypeBox host peers and exact Cursor SDK **1.0.40**. CI resolves the official version/fork commit once and retains exact SDK/CLI provenance. Types, tests and package checks use each selected host's consistent dependency graph; the locked development Pi **1.1.0** dependencies are reproducible snapshots, not qualification targets. Updating these snapshots does not upgrade the user's Pi installation or change the official Pi 0.87.1 minimum. After `npm ci --ignore-scripts`, run `node scripts/ci-compatibility.mjs --automation /path/to/automation` in an empty HOME/agent profile for credential-free latest qualification. Native macOS/Windows checks select the same resolved latest official graph. This builds the manifest entry, runs existing type/unit/package checks, and tests the compiled provider's registration plus production prompt shaping against native Pi transcript/tool transitions. Replay arguments must match their JSON stream deltas. A second native contract runs the registered Cursor provider with only its external SDK transport/storage substituted: real loopback bridge execution, display-only replay, persisted usage, incremental sends, tree navigation, compaction, request-boundary steering, abort and reload/disposal. Tests use no live Cursor service.
|
|
44
|
+
|
|
45
|
+
The frozen development `pi-coding-agent@1.1.0` input declares Undici 8.10.2. A version-scoped npm override selects released Undici 8.12.3 for that owner only, addressing its development audit findings without changing the Pi cohort or SDK transport. Dependency overrides apply only at the install root; this does not patch consumers' independently installed Pi hosts. Reassess the override when updating the development cohort.
|
|
46
|
+
|
|
47
|
+
TypeScript 7 builds and checks package types. Build and typecheck commands invoke `node_modules/typescript/bin/tsc` explicitly to avoid npm's shared `tsc` shim selecting a different compiler. `@typescript/typescript6` is dev-only for AST architecture and installed-SDK contract tests because TypeScript 7 does not expose a stable compiler API. Vitest 5 runs with `clearMocks: true` by default.
|
|
48
|
+
|
|
49
|
+
Pull-request CI runs that suite once per selected host: the latest stable official Pi and a source-built revision of the latest maintained fork `main`, each using its own consistent dependency graph and the version/commit resolved once for the run. It checks both npm and Git installations against both hosts without starting a Cursor model turn. The selected official version and fork commit are printed in the check log. Separate macOS and Windows jobs install with lifecycle scripts, load `node-pty`, and run the platform-build test, typecheck, and pack checks on Node 24.
|
|
50
|
+
|
|
51
|
+
For authorized uncommitted repairs, qualify an isolated immutable working-tree snapshot without committing:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
node scripts/ci-compatibility.mjs --working-tree --official-only --versions 0.87.1,0.99.1,1.0.3
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This builds and packs the snapshot, checks package loading, and exercises actual official native provider/session flows. The default invocation still requires a clean checkout and includes the maintained fork. `--help` documents selection and exit codes.
|
|
58
|
+
|
|
59
|
+
This manual snapshot mode retains explicit older-host qualification for the advertised floor; it is separate from CI's once-resolved latest-only targets. Do not combine manual selection flags with `--automation`.
|
|
60
|
+
|
|
61
|
+
This is offline compatibility proof, not Cursor authentication, desktop/cloud execution, visual, or all-platform live proof. Add only necessary changed-behavior live evidence under the [cost-conscious verification policy](#maintainer-cost-conscious-verification); the comprehensive paid matrix is optional, and paid Cloud testing is restricted to explicitly Cursor Cloud-focused PRs/issues. Older advertised Pi/Node floors require their own offline compatibility evidence.
|
|
62
|
+
|
|
63
|
+
Run checks:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm test
|
|
67
|
+
npm run typecheck
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Check the reviewable Cursor fallback catalog against the authenticated live catalog before releases:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
CURSOR_API_KEY="your-key" npm run check:cursor-snapshots
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Refresh it after Cursor model changes:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
CURSOR_API_KEY="your-key" npm run refresh:cursor-snapshots -- --write
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Refresh the bundled default/non-Max context-window snapshot only when checkpoint-derived context windows have been collected from live local runs:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
CURSOR_API_KEY="your-key" npm run refresh:cursor-snapshots -- --write \
|
|
86
|
+
--context-windows ~/.pi/agent/cursor-sdk-context-windows.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The check and refresh modes fetch and sort the same sanitized live catalog. Check mode byte-compares the generated fallback without writing; generated provenance records the installed `@cursor/sdk` version and model count. Both modes print public model metadata only and scrub known auth material from SDK errors. Do not run them with shell tracing that would echo API keys.
|
|
90
|
+
|
|
91
|
+
Local development run:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm install
|
|
95
|
+
CURSOR_API_KEY="your-key" pi --approve -e . --model cursor/grok-4.6
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
After editing `src/`, run `npm run build` before the next `pi -e .` run, or pi loads the previous build.
|
|
99
|
+
|
|
100
|
+
Maintainer design notes live in [`docs/cursor-model-ux-spec.md`](./cursor-model-ux-spec.md).
|
|
101
|
+
|
|
@@ -26,7 +26,7 @@ Meaningful gap closed: earlier card assertions could pass when the prompt mentio
|
|
|
26
26
|
|
|
27
27
|
## Registry visual classification
|
|
28
28
|
|
|
29
|
-
The implementation must classify every `CURSOR_TOOL_PRESENTATION_SPECS` entry from `src/cursor-tool-presentation-registry.ts` as required or excluded for the optional comprehensive visual matrix.
|
|
29
|
+
The implementation must classify every `CURSOR_TOOL_PRESENTATION_SPECS` entry from `src/cursor-tool-presentation-registry.ts` as required or excluded for the optional comprehensive visual matrix. `test/smoke-tooling.test.ts` fails when a registry tool name is missing from these lists or an excluded entry lacks a rationale.
|
|
30
30
|
|
|
31
31
|
Required deterministic cards:
|
|
32
32
|
|
|
@@ -40,6 +40,7 @@ Required deterministic cards:
|
|
|
40
40
|
|
|
41
41
|
Excluded from release visual matrix with required rationale:
|
|
42
42
|
|
|
43
|
+
- `ls`: composer-2-5 does not route the deterministic source-enumeration step through the native `ls` surface reliably; the suite instead gates that behavior through a successful native `find` result for `src/cursor-provider.ts`.
|
|
43
44
|
- `delete`: destructive and redundant with file mutation card coverage.
|
|
44
45
|
- `readLints`: dependent on target diagnostics state.
|
|
45
46
|
- `updateTodos`: model workflow dependent.
|
|
@@ -52,7 +53,7 @@ Excluded from release visual matrix with required rationale:
|
|
|
52
53
|
- `webSearch`: network/search dependent.
|
|
53
54
|
- `webFetch`: network dependent.
|
|
54
55
|
|
|
55
|
-
Adding a registry entry requires adding it to the required or excluded list with rationale.
|
|
56
|
+
Adding a registry entry requires adding it to the required or excluded list with rationale.
|
|
56
57
|
|
|
57
58
|
## Platform command rendering
|
|
58
59
|
|