pi-cursor-sdk 0.1.55 → 0.1.57
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 +60 -2
- package/README.md +100 -28
- package/docs/cursor-live-smoke-checklist.md +7 -7
- package/docs/cursor-model-ux-spec.md +48 -41
- package/docs/cursor-native-tool-replay.md +4 -4
- package/docs/cursor-native-tool-visual-audit.md +1 -1
- package/docs/cursor-testing-lessons.md +20 -7
- package/docs/cursor-tool-surfaces.md +13 -2
- package/docs/platform-smoke-implementation.md +220 -0
- package/docs/platform-smoke.md +183 -247
- package/package.json +39 -7
- package/platform-smoke.config.mjs +5 -1
- package/scripts/cloud-runtime-smoke.d.mts +3 -0
- package/scripts/cloud-runtime-smoke.mjs +502 -0
- package/scripts/debug-provider-events.mjs +7 -2
- package/scripts/isolated-cursor-smoke.sh +4 -6
- package/scripts/lib/cursor-child-process.d.mts +1 -0
- package/scripts/lib/cursor-child-process.mjs +137 -7
- package/scripts/lib/local-resume-smoke-harness.mjs +543 -0
- package/scripts/local-resume-cleanup-smoke.mjs +108 -0
- package/scripts/local-resume-smoke.d.mts +1 -0
- package/scripts/local-resume-smoke.mjs +642 -0
- package/scripts/platform-smoke/artifact-anchored-extract.d.mts +10 -0
- package/scripts/platform-smoke/artifact-anchored-extract.mjs +111 -0
- package/scripts/platform-smoke/artifact-bundle-chunk.mjs +57 -0
- package/scripts/platform-smoke/artifact-bundle-contract.mjs +34 -0
- package/scripts/platform-smoke/artifact-fs-safety.mjs +311 -0
- package/scripts/platform-smoke/artifact-openat-extract.c +335 -0
- package/scripts/platform-smoke/artifact-secrets.mjs +155 -0
- package/scripts/platform-smoke/artifacts.mjs +293 -65
- package/scripts/platform-smoke/card-detect.mjs +16 -4
- package/scripts/platform-smoke/crabbox-runner.mjs +45 -3
- package/scripts/platform-smoke/doctor.mjs +20 -10
- package/scripts/platform-smoke/live-suite-runner.mjs +18 -57
- package/scripts/platform-smoke/local-resume-runner.mjs +252 -0
- package/scripts/platform-smoke/local-resume-suites.d.mts +15 -0
- package/scripts/platform-smoke/local-resume-suites.mjs +104 -0
- package/scripts/platform-smoke/scenarios.mjs +16 -2
- package/scripts/platform-smoke/target-runtime.mjs +206 -0
- package/scripts/platform-smoke/targets.mjs +33 -141
- package/scripts/platform-smoke/visual-evidence.mjs +6 -7
- package/scripts/platform-smoke/wrapped-line-match.mjs +9 -0
- package/scripts/platform-smoke.mjs +40 -27
- package/scripts/refresh-cursor-model-snapshots.mjs +18 -6
- package/scripts/steering-rpc-smoke.mjs +12 -2
- package/scripts/tmux-live-smoke.sh +3 -5
- package/shared/cursor-cloud-lifecycle-constants.d.mts +3 -0
- package/shared/cursor-cloud-lifecycle-constants.mjs +7 -0
- package/shared/cursor-sensitive-text.mjs +7 -1
- package/src/context.ts +5 -2
- package/src/cursor-agents-context-registration.ts +7 -0
- package/src/cursor-agents-context.ts +3 -1
- package/src/cursor-api-key.ts +15 -1
- package/src/cursor-bridge-contract.ts +3 -0
- package/src/cursor-cloud-lifecycle.ts +733 -0
- package/src/cursor-cloud-options.ts +206 -0
- package/src/cursor-cloud-reporting.ts +246 -0
- package/src/cursor-config.ts +659 -0
- package/src/cursor-display-only-trace.ts +14 -0
- package/src/cursor-display-text.ts +8 -2
- package/src/cursor-durable-fs.ts +49 -0
- package/src/cursor-fallback-models.generated.ts +2045 -485
- package/src/cursor-live-run-accounting.ts +7 -1
- package/src/cursor-live-run-coordinator.ts +1 -0
- package/src/cursor-pi-tool-bridge-run.ts +14 -4
- package/src/cursor-provider-errors.ts +31 -5
- package/src/cursor-provider-live-run-drain.ts +5 -0
- package/src/cursor-provider-run-finalizer.ts +37 -28
- package/src/cursor-provider-run-outcome.ts +7 -2
- package/src/cursor-provider-turn-finalize.ts +77 -7
- package/src/cursor-provider-turn-prepare.ts +228 -12
- package/src/cursor-provider-turn-runner.ts +42 -13
- package/src/cursor-provider-turn-send.ts +59 -16
- package/src/cursor-provider-turn-types.ts +44 -10
- package/src/cursor-runtime-state.ts +478 -0
- package/src/cursor-sdk-event-debug.ts +46 -6
- package/src/cursor-sdk-process-error-guard.ts +101 -30
- package/src/cursor-session-agent-cleanup.ts +328 -0
- package/src/cursor-session-agent-resume.ts +439 -0
- package/src/cursor-session-agent.ts +109 -13
- package/src/cursor-session-scope.ts +35 -2
- package/src/cursor-session-send-policy.ts +1 -1
- package/src/cursor-skill-tool.ts +30 -11
- package/src/cursor-state.ts +112 -69
- package/src/cursor-tool-manifest.ts +1 -1
- package/src/cursor-usage-accounting.ts +14 -4
- package/src/index.ts +11 -2
- package/src/model-discovery.ts +10 -56
package/docs/platform-smoke.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Platform Smoke Gate
|
|
2
2
|
|
|
3
|
-
Status: current release gate for Cursor provider/runtime changes. The Crabbox runner, packed-install platform-build suite, and real live PTY/ConPTY suite runner are implemented for macOS, Ubuntu, and Windows native targets with one-lease-per-target orchestration.
|
|
3
|
+
Status: current local-runtime release gate for Cursor provider/runtime changes. Cloud-runtime changes also require the opt-in `npm run smoke:cloud` lane. The Crabbox runner, packed-install platform-build suite, and real live PTY/ConPTY suite runner are implemented for macOS, Ubuntu, and Windows native targets with one-lease-per-target orchestration.
|
|
4
|
+
|
|
5
|
+
Detailed detector, registry, command-rendering, implementation-history, replacement, and portability reference: [Platform Smoke Implementation Reference](./platform-smoke-implementation.md).
|
|
4
6
|
|
|
5
7
|
Branch introduced by: `feat/crabbox-platform-smoke`
|
|
6
8
|
|
|
@@ -10,7 +12,7 @@ Crabbox best-practice baseline applied from `~/Projects/crabbox`: Crabbox owns l
|
|
|
10
12
|
|
|
11
13
|
## Decision
|
|
12
14
|
|
|
13
|
-
Crabbox is the required platform smoke runner for `pi-cursor-sdk` releases that touch Cursor provider/runtime behavior.
|
|
15
|
+
Crabbox is the required local platform smoke runner for `pi-cursor-sdk` releases that touch Cursor provider/runtime behavior. PRs that touch actual cloud runtime execution must also run `npm run smoke:cloud`.
|
|
14
16
|
|
|
15
17
|
Inner-loop checks remain useful, but they are not release gates:
|
|
16
18
|
|
|
@@ -19,12 +21,18 @@ npm run verify
|
|
|
19
21
|
npm pack --dry-run
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
The required release gate is exactly:
|
|
24
|
+
The required local release gate is exactly:
|
|
23
25
|
|
|
24
26
|
```bash
|
|
25
27
|
npm run smoke:platform:all
|
|
26
28
|
```
|
|
27
29
|
|
|
30
|
+
Cloud-runtime changes additionally require:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run smoke:cloud
|
|
34
|
+
```
|
|
35
|
+
|
|
28
36
|
`smoke:platform:all` runs `smoke:platform:doctor` first and only starts the target matrix after doctor passes. Maintainers may still run `npm run smoke:platform:doctor` by itself for setup diagnosis.
|
|
29
37
|
|
|
30
38
|
|
|
@@ -35,7 +43,7 @@ No partial adoption exists. The release evidence must include macOS, Ubuntu, and
|
|
|
35
43
|
## Non-negotiable constraints
|
|
36
44
|
|
|
37
45
|
- No GitHub Actions dependency.
|
|
38
|
-
- No cloud provider dependency.
|
|
46
|
+
- No cloud provider dependency in the default local platform gate; cloud-runtime changes use the separate opt-in cloud lane.
|
|
39
47
|
- No Crabbox broker/coordinator dependency.
|
|
40
48
|
- No release gate that runs on only one operating system.
|
|
41
49
|
- No release gate that proves command behavior but not TUI visual behavior.
|
|
@@ -110,6 +118,16 @@ start target session
|
|
|
110
118
|
run cursor-native-visual-matrix
|
|
111
119
|
run cursor-bridge-visual-matrix
|
|
112
120
|
run cursor-abort-cleanup
|
|
121
|
+
run cursor-local-resume-restart
|
|
122
|
+
run cursor-local-resume-safety
|
|
123
|
+
run cursor-local-resume-tool-surface
|
|
124
|
+
run cursor-local-resume-abort
|
|
125
|
+
run cursor-local-resume-tree
|
|
126
|
+
run cursor-local-resume-copy-switch
|
|
127
|
+
run cursor-local-resume-fallback
|
|
128
|
+
run cursor-local-resume-compaction
|
|
129
|
+
run cursor-local-resume-default-dry-run
|
|
130
|
+
run cursor-local-resume-cleanup
|
|
113
131
|
download artifacts after every suite
|
|
114
132
|
stop target
|
|
115
133
|
write lease-cleanup stop evidence
|
|
@@ -123,7 +141,7 @@ Runtime budget is part of the contract:
|
|
|
123
141
|
- `smoke:platform:doctor` never calls Cursor.
|
|
124
142
|
- `platform-build` runs once per target and is the only suite that performs the full local CI/build/typecheck/package gate.
|
|
125
143
|
- Live suites reuse the target checkout and prepared `node_modules` when run after `platform-build`; they do not repeat `npm ci` in a target-session release run.
|
|
126
|
-
- Live suites share one target-local packed-install prep directory per target-session release run. The first
|
|
144
|
+
- Live and local-resume suites share one target-local packed-install prep directory per target-session release run. The first such suite runs `npm pack` and `npm install --no-save <tarball>` once. Visual/abort suites install that packed path with `pi install --approve -l`; local-resume lanes pass the same packed package path to their source-tree smoke harness instead of loading the checkout extension.
|
|
127
145
|
- Visual coverage is batched into one native prompt, one bridge prompt, and one abort/cleanup prompt per target. Do not split these into one prompt per card.
|
|
128
146
|
- The gate is fail-fast by target to avoid burning Cursor calls after a platform has already failed.
|
|
129
147
|
|
|
@@ -137,6 +155,60 @@ Runtime budget is part of the contract:
|
|
|
137
155
|
|
|
138
156
|
Ubuntu is covered as its own local-container target, and Windows native remains a full visual TUI target.
|
|
139
157
|
|
|
158
|
+
## Opt-in cloud smoke lane
|
|
159
|
+
|
|
160
|
+
Cloud validation is intentionally separate from `smoke:platform:all`. The required release gate keeps **no cloud provider dependency**; cloud runtime PRs must also run the opt-in cloud lane when they touch actual cloud execution.
|
|
161
|
+
|
|
162
|
+
Run:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npm run smoke:cloud
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The default lane is intentionally minimal: it starts one non-interactive cloud run in a fresh persisted pi session (Cloud rejects `--no-session` so lifecycle intent can be fsynced before remote work), with explicit acknowledgement, fresh context, no pi bridge, no env forwarding, SDK event-debug contract checks, bounded stream-only cloud report shape checks, and cloud-agent archival cleanup with post-archive `archived: true` verification. Raw usage/artifact presence is account-dependent, so display-only accounting and artifact formatting contracts stay covered by unit/provider tests. It must fail closed when requested but unavailable:
|
|
169
|
+
|
|
170
|
+
- missing cloud-capable credentials, repo access, or cloud entitlement → report **blocked**, not skipped-ready;
|
|
171
|
+
- no non-interactive prompts; every needed cloud choice must come from CLI/env/config;
|
|
172
|
+
- do not expose inline cloud MCP in the first cloud runtime lane;
|
|
173
|
+
- do not forward local env values;
|
|
174
|
+
- harvest exact throwaway agent IDs from optional debug metadata plus canonical session JSONL/lifecycle journals, archive the full union, and verify archived metadata before passing;
|
|
175
|
+
- retain the entire artifact root whenever the run or any cleanup fails (successful runs remove it unless `CURSOR_CLOUD_SMOKE_KEEP_ARTIFACTS=1`).
|
|
176
|
+
|
|
177
|
+
Focused optional proof: `npm run smoke:cloud:context` runs a separate sessionful context-handoff matrix. Use it when changing cloud context-handoff behavior or gathering default-on/cloud-resume evidence. `fresh` must answer `NO_MARKER` for a prior-marker recall prompt, while `bootstrap` must recall the marker. It archives and verifies every exact cloud agent ID observed in debug metadata or canonical lifecycle artifacts.
|
|
178
|
+
|
|
179
|
+
Future expanded cloud smoke work should add throwaway repo/branch coverage, dirty/unpushed warning assertions, branch/PR behavior, explicit direct-push opt-in, missing-branch failure, cancel/delete cleanup, and account-backed artifact/raw-usage fixtures when those contracts need live proof beyond the current report-shape and context-handoff smokes.
|
|
180
|
+
|
|
181
|
+
This lane is a cloud-runtime release gate, not a substitute for the local macOS/Ubuntu/Windows `smoke:platform:all` gate.
|
|
182
|
+
|
|
183
|
+
## Focused local resume smoke
|
|
184
|
+
|
|
185
|
+
The platform matrix includes the required local-resume lanes: restart, safety, tool-surface, abort, tree, copy/switch, fallback, compaction, default/opt-out proof, and recorded-ID-only cleanup. Platform lanes run those scripts against the target's shared packed package path, then copy each lane's session JSONL, Cursor SDK debug metadata, runtime-launch record, and other bounded smoke artifacts into its canonical platform suite directory. The same scripts still load the source checkout by default when run directly as focused host-local inner-loop checks. Windows uses the intentionally short target-side evidence component `lr` so the Cursor SDK's derived SQLite path remains below legacy `MAX_PATH`; every suite removes and verifies that directory before use, failing closed on stale or locked evidence.
|
|
186
|
+
|
|
187
|
+
The smoke starts one sessionful local Cursor run with local resume enabled by default, records the SDK agent id from provider debug metadata, restarts pi against the same session, asks for the remembered marker, and verifies:
|
|
188
|
+
|
|
189
|
+
- the first run records `localResume: true` and `resumedAgent: false`;
|
|
190
|
+
- the second run records `localResume: true`, `resumedAgent: true`, and a one-time bootstrap send plan;
|
|
191
|
+
- both runs use the same local SDK `agent-*` id;
|
|
192
|
+
- the remembered marker survives the process restart from the bootstrapped current pi transcript.
|
|
193
|
+
|
|
194
|
+
The safety lane verifies an original session resumes the same local agent after restart, then proves cloned-session copied resume entries and a fork before a future-marker prompt both create a new local `agent-*`. The forked earlier branch must not reveal the future marker.
|
|
195
|
+
|
|
196
|
+
The tool-surface lane verifies same-session restart reuses the original local agent with the same bridge/tool surface, then enables the builtin pi tool bridge surface and verifies the old resume handle is rejected, a bridge run is created, a new local `agent-*` is used, and a new resume pool key is persisted.
|
|
197
|
+
|
|
198
|
+
The abort lane verifies a completed bridge-enabled turn persists a local resume handle, an interrupted long-running bridge turn starts from that handle but does not append a new one, and the next same-surface restart uses a new local `agent-*` instead of resuming the pre-abort agent.
|
|
199
|
+
|
|
200
|
+
The tree lane verifies both realistic navigation to an earlier assistant entry and direct navigation to an earlier `cursor-sdk-agent-resume` custom entry reject the future-seeing SDK agent and do not reveal the future-only marker.
|
|
201
|
+
|
|
202
|
+
The copy/switch lane copies a session file containing resume custom entries, switches to that copied file, and verifies the copied handle is rejected while transcript bootstrap still recalls the marker.
|
|
203
|
+
|
|
204
|
+
The fallback lane rewrites a persisted handle to a missing local SDK `agent-*`, verifies create+bootstrap fallback, and asserts the continuity notice is emitted in `pi-stream-events.jsonl`.
|
|
205
|
+
|
|
206
|
+
The compaction lane uses an isolated temp pi settings file with `compaction.keepRecentTokens: 1` to force manual compaction without huge dummy prompts. It verifies the pre-compaction SDK agent is not reused, the new handle records `compactionGeneration: 1`, and restart resumes the post-compaction agent.
|
|
207
|
+
|
|
208
|
+
The default/opt-out lane verifies the built-in local resume default resumes, then verifies `PI_CURSOR_LOCAL_RESUME=0` opts out and creates a new agent while bootstrapping the transcript.
|
|
209
|
+
|
|
210
|
+
The cleanup lane verifies `/cursor-local-resume-cleanup --dry-run` reports only recorded superseded local `agent-*` IDs, `/cursor-local-resume-cleanup --yes` verifies and fsyncs intent before deleting exactly the old recorded ID and fsyncs the result afterward, the current recorded agent still resumes, and tree navigation to the old handle falls back instead of resuming the deleted agent.
|
|
211
|
+
|
|
140
212
|
## Files and scripts
|
|
141
213
|
|
|
142
214
|
Files:
|
|
@@ -144,6 +216,10 @@ Files:
|
|
|
144
216
|
```text
|
|
145
217
|
platform-smoke.config.mjs
|
|
146
218
|
scripts/platform-smoke.mjs
|
|
219
|
+
scripts/platform-smoke/artifact-bundle-chunk.mjs
|
|
220
|
+
scripts/platform-smoke/artifact-bundle-contract.mjs
|
|
221
|
+
scripts/platform-smoke/artifact-fs-safety.mjs
|
|
222
|
+
scripts/platform-smoke/artifact-secrets.mjs
|
|
147
223
|
scripts/platform-smoke/assertions.mjs
|
|
148
224
|
scripts/platform-smoke/artifacts.mjs
|
|
149
225
|
scripts/platform-smoke/card-detect.mjs
|
|
@@ -151,25 +227,48 @@ scripts/platform-smoke/crabbox-runner.mjs
|
|
|
151
227
|
scripts/platform-smoke/doctor.mjs
|
|
152
228
|
scripts/platform-smoke/jsonl-text.mjs
|
|
153
229
|
scripts/platform-smoke/live-suite-runner.mjs
|
|
230
|
+
scripts/platform-smoke/local-resume-runner.mjs
|
|
231
|
+
scripts/platform-smoke/local-resume-suites.mjs
|
|
154
232
|
scripts/platform-smoke/platform-build-windows.ps1
|
|
155
233
|
scripts/platform-smoke/pty-capture.mjs
|
|
156
234
|
scripts/platform-smoke/render-ansi.mjs
|
|
157
235
|
scripts/platform-smoke/scenarios.mjs
|
|
236
|
+
scripts/platform-smoke/target-runtime.mjs
|
|
158
237
|
scripts/platform-smoke/targets.mjs
|
|
159
238
|
scripts/platform-smoke/visual-evidence.mjs
|
|
239
|
+
scripts/platform-smoke/wrapped-line-match.mjs
|
|
160
240
|
```
|
|
161
241
|
|
|
242
|
+
`artifact-bundle-contract.mjs` owns bundle transport markers/path/size caps and the canonical
|
|
243
|
+
exact-size base64 decoder. `artifact-secrets.mjs` owns redaction patterns and scanning.
|
|
244
|
+
`artifact-fs-safety.mjs` owns no-follow traversal/identity primitives, bounded reads, safe
|
|
245
|
+
extraction writes/cleanup, and the exclusive bundle spill writer. `artifacts.mjs` retains
|
|
246
|
+
retention/manifest/index bookkeeping and bundle build/format/extract orchestration on top of
|
|
247
|
+
those three modules, re-exporting their public names for backward compatibility.
|
|
248
|
+
|
|
162
249
|
Package scripts:
|
|
163
250
|
|
|
164
251
|
```json
|
|
165
252
|
{
|
|
166
|
-
"check:platform-smoke": "node --check platform-smoke.config.mjs && node --check <platform smoke scripts> && vitest run test/smoke-tooling.test.ts",
|
|
253
|
+
"check:platform-smoke": "node --check platform-smoke.config.mjs && node --check <platform smoke scripts> && vitest run test/platform-artifact-boundaries.test.ts test/platform-smoke-artifact-transport.test.ts test/smoke-cli-package-contracts.test.ts test/smoke-tooling.test.ts",
|
|
167
254
|
"smoke:platform": "node scripts/platform-smoke.mjs",
|
|
168
255
|
"smoke:platform:doctor": "node scripts/platform-smoke.mjs doctor",
|
|
169
256
|
"smoke:platform:macos": "node scripts/platform-smoke.mjs run --target macos",
|
|
170
257
|
"smoke:platform:ubuntu": "node scripts/platform-smoke.mjs run --target ubuntu",
|
|
171
258
|
"smoke:platform:windows-native": "node scripts/platform-smoke.mjs run --target windows-native",
|
|
172
|
-
"smoke:platform:all": "npm run smoke:platform:doctor && node scripts/platform-smoke.mjs run --target macos,ubuntu,windows-native"
|
|
259
|
+
"smoke:platform:all": "npm run smoke:platform:doctor && node scripts/platform-smoke.mjs run --target macos,ubuntu,windows-native",
|
|
260
|
+
"smoke:cloud": "node scripts/cloud-runtime-smoke.mjs",
|
|
261
|
+
"smoke:cloud:context": "node scripts/cloud-runtime-smoke.mjs --context-matrix",
|
|
262
|
+
"smoke:local-resume": "node scripts/local-resume-smoke.mjs",
|
|
263
|
+
"smoke:local-resume:safety": "node scripts/local-resume-smoke.mjs --safety",
|
|
264
|
+
"smoke:local-resume:tool-surface": "node scripts/local-resume-smoke.mjs --tool-surface",
|
|
265
|
+
"smoke:local-resume:abort": "node scripts/local-resume-smoke.mjs --abort",
|
|
266
|
+
"smoke:local-resume:tree": "node scripts/local-resume-smoke.mjs --tree",
|
|
267
|
+
"smoke:local-resume:copy-switch": "node scripts/local-resume-smoke.mjs --copy-switch",
|
|
268
|
+
"smoke:local-resume:fallback": "node scripts/local-resume-smoke.mjs --fallback",
|
|
269
|
+
"smoke:local-resume:compaction": "node scripts/local-resume-smoke.mjs --compaction",
|
|
270
|
+
"smoke:local-resume:default-dry-run": "node scripts/local-resume-smoke.mjs --default-dry-run",
|
|
271
|
+
"smoke:local-resume:cleanup": "node scripts/local-resume-smoke.mjs --cleanup"
|
|
173
272
|
}
|
|
174
273
|
```
|
|
175
274
|
|
|
@@ -182,6 +281,8 @@ All repo-specific behavior lives in `platform-smoke.config.mjs` so the framework
|
|
|
182
281
|
Required config fields:
|
|
183
282
|
|
|
184
283
|
```js
|
|
284
|
+
import { LOCAL_RESUME_SUITE_NAMES } from "./scripts/platform-smoke/local-resume-suites.mjs";
|
|
285
|
+
|
|
185
286
|
export default {
|
|
186
287
|
packageName: "pi-cursor-sdk",
|
|
187
288
|
cursorModel: "cursor/composer-2-5",
|
|
@@ -197,12 +298,14 @@ export default {
|
|
|
197
298
|
"cursor-native-visual-matrix",
|
|
198
299
|
"cursor-bridge-visual-matrix",
|
|
199
300
|
"cursor-abort-cleanup",
|
|
301
|
+
...LOCAL_RESUME_SUITE_NAMES,
|
|
200
302
|
],
|
|
201
303
|
requiredCrabbox: {
|
|
202
304
|
install: "Homebrew package or PLATFORM_SMOKE_CRABBOX override",
|
|
203
305
|
minVersion: "0.26.0",
|
|
204
306
|
},
|
|
205
|
-
ubuntuContainerImage: "
|
|
307
|
+
ubuntuContainerImage: "pi-cursor-sdk-platform-node:24.16-root",
|
|
308
|
+
ubuntuContainerBaseImage: "cimg/node:24.16",
|
|
206
309
|
nodeValidationMajor: 24,
|
|
207
310
|
windowsParallels: {
|
|
208
311
|
sourceVm: "pi-extension-windows-template",
|
|
@@ -212,7 +315,7 @@ export default {
|
|
|
212
315
|
};
|
|
213
316
|
```
|
|
214
317
|
|
|
215
|
-
`
|
|
318
|
+
`ubuntuContainerBaseImage` is the Ubuntu 24.04 Node 24 base with the current glibc baseline for native test dependencies. The runner builds the local `ubuntuContainerImage` wrapper with only `USER root` changed before warmup because Crabbox 0.36.0 must install SSH/Git/rsync/curl during bootstrap and `cimg/node` defaults to an unprivileged user. An explicit `PLATFORM_SMOKE_UBUNTU_IMAGE` bypasses that build and must already support Crabbox bootstrap. `nodeValidationMajor: 24` is the release-smoke validation baseline. It does not change the package engine by itself. A separate compatibility lane can test Node 22.19 later; this required gate validates Node 24 on every target.
|
|
216
319
|
|
|
217
320
|
`windowsParallels` records this repo's default shared Windows template contract. Environment overrides may point at a temporary candidate template during infrastructure work, but release runs should use the shared `pi-extension-windows-template` / `crabbox-ready` baseline unless this document is updated.
|
|
218
321
|
|
|
@@ -229,7 +332,8 @@ PLATFORM_SMOKE_CRABBOX=/opt/homebrew/bin/crabbox
|
|
|
229
332
|
PLATFORM_SMOKE_MAC_HOST=localhost
|
|
230
333
|
PLATFORM_SMOKE_MAC_USER="$USER"
|
|
231
334
|
PLATFORM_SMOKE_MAC_WORK_ROOT="/Users/$USER/crabbox/pi-cursor-sdk"
|
|
232
|
-
|
|
335
|
+
# Optional prebuilt replacement; bypasses the configured local root-wrapper build.
|
|
336
|
+
PLATFORM_SMOKE_UBUNTU_IMAGE="registry.example.com/ubuntu-node24-crabbox:latest"
|
|
233
337
|
|
|
234
338
|
# Optional Parallels overrides; defaults come from platform-smoke.config.mjs.
|
|
235
339
|
PLATFORM_SMOKE_WINDOWS_VM="pi-extension-windows-template"
|
|
@@ -410,6 +514,34 @@ Purpose:
|
|
|
410
514
|
|
|
411
515
|
The host `smoke:platform:all` entrypoint enforces doctor first before running targets. Required artifacts include `node-version.txt`, `npm-version.txt`, stdout/stderr for `npm ci`, `npm run check:platform-smoke`, `npm test`, `npm run typecheck`, `npm pack`, packed npm install, `pi install --approve`, and `pi list --approve`, plus `packed-tarball.txt`, `summary.json`, `artifact-manifest.json`, `assertions.json`, and `failures.md` on failed assertions.
|
|
412
516
|
|
|
517
|
+
### `cursor-local-resume-restart`
|
|
518
|
+
|
|
519
|
+
Cursor calls: `2`.
|
|
520
|
+
|
|
521
|
+
Purpose:
|
|
522
|
+
|
|
523
|
+
- prove guarded local resume default-on behavior across a pi process restart on each required OS;
|
|
524
|
+
- assert the first turn creates a local `agent-*` and the second turn resumes the same `agent-*`;
|
|
525
|
+
- force local runtime and clear cloud env knobs so ambient cloud settings cannot satisfy this suite.
|
|
526
|
+
|
|
527
|
+
The suite prepares or reuses the target's packed npm install, runs `npm run smoke:local-resume` with that packed extension path, and asserts the `local-resume-smoke-ok` marker plus the resumed local agent id line. It also requires extracted session, debug, and runtime-launch evidence under `local-resume-evidence/`; checkout `pi -e <repo-root>` is reserved for the standalone inner-loop command.
|
|
528
|
+
|
|
529
|
+
### `cursor-local-resume-*` focused proof lanes
|
|
530
|
+
|
|
531
|
+
The remaining local-resume platform suites run the matching focused package script against the shared packed extension on each target, retain the same evidence categories, and assert its success marker plus stderr evidence line:
|
|
532
|
+
|
|
533
|
+
| Suite | Package script | Purpose |
|
|
534
|
+
| --- | --- | --- |
|
|
535
|
+
| `cursor-local-resume-safety` | `npm run smoke:local-resume:safety` | clone rejection and fork-before-future no-leak |
|
|
536
|
+
| `cursor-local-resume-tool-surface` | `npm run smoke:local-resume:tool-surface` | stale handle rejection after bridge/tool-surface change |
|
|
537
|
+
| `cursor-local-resume-abort` | `npm run smoke:local-resume:abort` | interrupted bridge turn does not persist/reuse stale handle |
|
|
538
|
+
| `cursor-local-resume-tree` | `npm run smoke:local-resume:tree` | earlier assistant and resume-entry tree targets reject future-seeing agent |
|
|
539
|
+
| `cursor-local-resume-copy-switch` | `npm run smoke:local-resume:copy-switch` | copied session file rejects copied resume handle |
|
|
540
|
+
| `cursor-local-resume-fallback` | `npm run smoke:local-resume:fallback` | missing local agent falls back with continuity notice |
|
|
541
|
+
| `cursor-local-resume-compaction` | `npm run smoke:local-resume:compaction` | compaction boundary creates/resumes post-compaction generation |
|
|
542
|
+
| `cursor-local-resume-default-dry-run` | `npm run smoke:local-resume:default-dry-run` | built-in default resumes and env opt-out wins |
|
|
543
|
+
| `cursor-local-resume-cleanup` | `npm run smoke:local-resume:cleanup` | recorded-ID-only cleanup deletes old agent and preserves current agent |
|
|
544
|
+
|
|
413
545
|
### `cursor-native-visual-matrix`
|
|
414
546
|
|
|
415
547
|
Cursor calls: `1`.
|
|
@@ -619,13 +751,23 @@ Per target maximum live Cursor invocations:
|
|
|
619
751
|
cursor-native-visual-matrix: 1
|
|
620
752
|
cursor-bridge-visual-matrix: 1
|
|
621
753
|
cursor-abort-cleanup: 1
|
|
754
|
+
cursor-local-resume-restart: 2
|
|
755
|
+
cursor-local-resume-safety: 5
|
|
756
|
+
cursor-local-resume-tool-surface: 3
|
|
757
|
+
cursor-local-resume-abort: 3
|
|
758
|
+
cursor-local-resume-tree: 4
|
|
759
|
+
cursor-local-resume-copy-switch: 2
|
|
760
|
+
cursor-local-resume-fallback: 2
|
|
761
|
+
cursor-local-resume-compaction: 5
|
|
762
|
+
cursor-local-resume-default-dry-run: 3
|
|
763
|
+
cursor-local-resume-cleanup: 4
|
|
622
764
|
```
|
|
623
765
|
|
|
624
|
-
Maximum per target: `
|
|
766
|
+
Maximum per target: `36` Cursor invocations.
|
|
625
767
|
|
|
626
|
-
Maximum full gate: `
|
|
768
|
+
Maximum full gate: `108` Cursor invocations.
|
|
627
769
|
|
|
628
|
-
The merge gate is `npm run smoke:platform:all`; that script runs doctor first and then the matrix to preserve this budget. No suite adds a new Cursor invocation without updating this plan and `platform-smoke.
|
|
770
|
+
The merge gate is `npm run smoke:platform:all`; that script runs doctor first and then the matrix to preserve this budget. No suite adds a new Cursor invocation without updating this plan and the scenario source of truth (`scripts/platform-smoke/scenarios.mjs`, plus `scripts/platform-smoke/local-resume-suites.mjs` for local-resume lanes).
|
|
629
771
|
|
|
630
772
|
## Artifact contract
|
|
631
773
|
|
|
@@ -647,7 +789,7 @@ After each `smoke:platform run` invocation, the host writes an atomic latest art
|
|
|
647
789
|
.artifacts/platform-smoke/latest.json
|
|
648
790
|
```
|
|
649
791
|
|
|
650
|
-
`latest.json` records the invocation timestamps, command selection, PID, run id(s), target/suite artifact directories, paths to suite summaries/assertions/failures when present, rendered terminal HTML/PNG paths, visual evidence, session JSONL, JSONL tool-result summaries,
|
|
792
|
+
`latest.json` records the invocation timestamps, command selection, PID, run id(s), target/suite artifact directories, paths to suite summaries/assertions/failures when present, rendered terminal HTML/PNG paths, visual evidence, session JSONL, JSONL tool-result summaries, capped Cursor SDK/provider debug artifact paths, and local-resume evidence roots/indexes/runtime-launch records. The per-suite artifact directories remain the source of truth; `latest.json` is only a discoverability pointer.
|
|
651
793
|
|
|
652
794
|
Common required artifacts:
|
|
653
795
|
|
|
@@ -730,6 +872,17 @@ cursor-sdk-events/
|
|
|
730
872
|
sessions/**/<turn-artifact>.json or .jsonl
|
|
731
873
|
```
|
|
732
874
|
|
|
875
|
+
Required local-resume artifacts:
|
|
876
|
+
|
|
877
|
+
```text
|
|
878
|
+
local-resume-evidence.json # counts retained files by evidence category
|
|
879
|
+
local-resume-evidence/
|
|
880
|
+
runtime-launches.jsonl # proves the packed extension path used by each pi process
|
|
881
|
+
sessions/**/*.jsonl
|
|
882
|
+
debug/**/* # Cursor SDK/provider turn metadata
|
|
883
|
+
agent/**/* # bounded non-secret runtime state when written
|
|
884
|
+
```
|
|
885
|
+
|
|
733
886
|
Required abort artifacts:
|
|
734
887
|
|
|
735
888
|
```text
|
|
@@ -743,27 +896,18 @@ Provider debug artifacts are required for every live suite through `PI_CURSOR_SD
|
|
|
743
896
|
|
|
744
897
|
## Artifact collection on failure
|
|
745
898
|
|
|
746
|
-
|
|
899
|
+
The target-side live and local-resume runners encode only canonical bounded text evidence as gzip-compressed JSON/base64. Unknown extensions are secret-scanned and then omitted when benign; a secret finding still fails the run. Binary content under a transport-eligible text extension fails with bounded `binary-content` evidence, and direct bundles containing either unknown extensions or binary content are never extracted. The inner bundle schema is exactly `{files}`, and each entry is exactly `{path, contentBase64, size}`: source-root and per-file metadata are rejected, canonical paths and decoded content are secret-scanned, secret-bearing paths are rejected, and filenames in findings are redacted. The caller-selected artifact root is a trust boundary. Its final component must be a real directory, and its real path must equal the same relative path mapped beneath the canonical real CWD or temp base. This permits expected platform base aliases such as macOS `/var` → `/private/var` but rejects user-created intermediate root links. Every traversed directory is secured with lstat/open/fstat/post-lstat identity checks (POSIX opens use `O_DIRECTORY|O_NOFOLLOW`), its descriptor stays open while descendants are visited, and all current/ancestor identities plus the original ctime, mtime, size, link count, and mode are rechecked around directory reads and bounded file reads. These immutable metadata checks apply only to traversal guards; extraction uses identity-only guards because creating destination entries legitimately mutates parent metadata. Every regular artifact file, regardless of name or extension, is binary-safe scanned from a descriptor-bounded snapshot before transport eligibility is checked. Binary scans retain exact `CURSOR_API_KEY`, generic auth assignments, and structured bearer/cookie/bridge/JSON signatures in UTF-8/ASCII, UTF-16LE/BE, and UTF-32LE/BE at any byte alignment; the intentionally broad generic credential-URL and SCP-style heuristics run only on valid UTF-8 text so random compressed/executable bytes cannot create false failures. Static child symlinks fail as non-regular entries; a nested rename/symlink ABA invalidates the whole traversal, discarding collected findings and bytes in favor of bounded failure evidence. Sensitive files (`.env*`, `auth.json`, `id_rsa`, `id_ed25519`, `*.pem`, and `*.key`) therefore fail the run when they contain secrets but are never transported. `node_modules/` and `.git/` are non-artifact infrastructure and are pruned before recursion. File size is checked before allocation or reading. An unreadable, changed, or oversized file fails closed; oversized files are not read and produce bounded limit evidence, while the host scanner reports an oversized or otherwise unscannable artifact as a finding so the suite fails. Bundles allow at most 512 files, 5 MiB per file, 40 MiB aggregate decoded content, 4,096 UTF-8 bytes per path, 4,096 total path components, 64 MiB inflated JSON, and 20 MiB compressed transport. The writer and extractor enforce the same limits; limit overflow emits only a bounded `bundle-limit-exceeded.json` failure artifact. Before host filesystem mutation, extraction rejects duplicate and file-prefix-conflicting paths, symlink/non-directory destination components, and pre-existing final paths. On POSIX controllers it sends the already prevalidated bounded files to the packaged `artifact-openat-extract.c` helper, compiled once into a private temporary directory. The helper independently validates the complete frame before mutation, requires its opened root identity to match the caller's pinned root, and uses descriptor-relative `mkdirat`/`openat` with `O_NOFOLLOW` one canonical component at a time. Substituted symlinks and pre-open path swaps therefore fail without following them, final files use `O_EXCL`, and detected identity drift rolls created files back through retained parent descriptors even when a directory was moved. This is race-safe extraction, not a sandbox against a hostile same-owner process: such a process can transiently relocate an already-open directory or the pinned root itself, although it cannot make extraction overwrite an existing destination. Windows controllers reject every nonempty extraction bundle before mutation because Node exposes no handle-relative Windows creation API; Windows remains a supported release target when the matrix is orchestrated from the macOS/POSIX controller. Small bundles stay between `PLATFORM_LIVE_BUNDLE_JSON_START` and `PLATFORM_LIVE_BUNDLE_JSON_END`; larger bundles exclusively create and descriptor-write the exact CWD-relative `.platform-artifact-bundle.gz` final component (`O_NOFOLLOW` on POSIX), emit that exact marker path, and allow chunk reads only for that one-component path. No intermediate spill path is accepted. Windows uses lstat identity checks for directories and lstat/fstat identity checks for regular files and the spill, without POSIX-only flags. The host retrieves exact 32 KiB chunks through no-sync Crabbox runs before releasing the lease. Compact control output is collected through Crabbox's local `--capture-stdout` file. This works on scenario failure and preserves the original command exit code; chunk transport success is not substituted for suite success, and no tar/zip side channel exists.
|
|
747
900
|
|
|
748
|
-
Required
|
|
901
|
+
Required fail-through behavior:
|
|
749
902
|
|
|
750
|
-
1. Run the scenario.
|
|
751
|
-
2.
|
|
752
|
-
3.
|
|
753
|
-
4.
|
|
754
|
-
5.
|
|
755
|
-
6.
|
|
756
|
-
|
|
757
|
-
Crabbox command exit means transport status. Suite pass/fail comes from `assertions.json`.
|
|
758
|
-
|
|
759
|
-
Archive names:
|
|
760
|
-
|
|
761
|
-
```text
|
|
762
|
-
<target>-<suite>-artifacts.tar.gz # macOS, Ubuntu
|
|
763
|
-
<target>-<suite>-artifacts.zip # Windows native
|
|
764
|
-
```
|
|
903
|
+
1. Run the scenario and write target-side session/debug/runtime evidence.
|
|
904
|
+
2. Encode the artifact bundle in a `finally` path after applying path, secret, file-size, file-count, aggregate, inflated-JSON, and compressed-size limits; emit it inline or write the marked gzip file. Any bound overflow or traversal invalidation must emit the bounded limit-failure artifact instead of partial evidence, prior findings, or bytes.
|
|
905
|
+
3. Preserve the real scenario process exit code in Crabbox output.
|
|
906
|
+
4. Before lease release, have the host fetch any marked chunks and call `extractPlatformArtifactBundle()` even for a nonzero result.
|
|
907
|
+
5. Write host-side `exit-code.txt`, `assertions.json`, and `failures.md` from the process result plus extracted evidence.
|
|
908
|
+
6. Verify the canonical `artifact-manifest.json`; missing or unsafe bundle content fails the suite.
|
|
765
909
|
|
|
766
|
-
|
|
910
|
+
There is no tar/zip side channel. Crabbox stdout carries the inline bundle or its authenticated retrieval marker/chunks, while the canonical host suite directory remains the durable source of truth.
|
|
767
911
|
|
|
768
912
|
## Assertion contract
|
|
769
913
|
|
|
@@ -791,81 +935,9 @@ Failures produce `failures.md` with:
|
|
|
791
935
|
- command summary;
|
|
792
936
|
- next diagnostic command.
|
|
793
937
|
|
|
794
|
-
## Visual evidence detector
|
|
795
|
-
|
|
796
|
-
The detector operates on host-rendered terminal HTML and PNG evidence. It must not pass from prompt text alone.
|
|
797
|
-
|
|
798
|
-
Required behavior:
|
|
799
|
-
|
|
800
|
-
- render ANSI with xterm/Playwright and assert the terminal DOM/theme is present, styled, non-empty, and screenshotted;
|
|
801
|
-
- search the rendered xterm buffer for suite-owned evidence patterns that correspond to actual tool output/results, not instructions in the prompt;
|
|
802
|
-
- scroll to each evidence line and write `cards/<evidence-id>.png` screenshots plus `visual-evidence.json`;
|
|
803
|
-
- write `cards.json` for the legacy rendered-evidence inventory;
|
|
804
|
-
- fail when required visual evidence is missing;
|
|
805
|
-
- fail when a card/evidence item has the wrong success/error state;
|
|
806
|
-
- fail when footer/status is missing or unreadable.
|
|
807
|
-
|
|
808
|
-
Meaningful gap closed: earlier card assertions could pass when the prompt mentioned `pi__read` or a missing-file path even if the actual tool card/result never rendered. The gate now requires JSONL result evidence and per-evidence rendered screenshots for native read, native shell success/failure, native edit diffs, bridge read success/failure, and bridge shell success.
|
|
809
|
-
|
|
810
|
-
## Registry visual classification
|
|
811
|
-
|
|
812
|
-
The implementation must classify every `CURSOR_TOOL_PRESENTATION_SPECS` entry from `src/cursor-tool-presentation-registry.ts` as required or excluded for the release visual gate. A validation check fails when a registry entry lacks classification.
|
|
813
|
-
|
|
814
|
-
Required deterministic cards:
|
|
815
|
-
|
|
816
|
-
- `read`
|
|
817
|
-
- `grep`
|
|
818
|
-
- `glob` / find
|
|
819
|
-
- `shell`
|
|
820
|
-
- `write`
|
|
821
|
-
- `edit`
|
|
822
|
-
- failed `read`
|
|
823
|
-
|
|
824
|
-
Excluded from release visual matrix with required rationale:
|
|
825
|
-
|
|
826
|
-
- `delete`: destructive and redundant with file mutation card coverage.
|
|
827
|
-
- `readLints`: dependent on target diagnostics state.
|
|
828
|
-
- `updateTodos`: model workflow dependent.
|
|
829
|
-
- `createPlan`: model workflow dependent.
|
|
830
|
-
- `task`: model/task orchestration dependent.
|
|
831
|
-
- `generateImage`: external image generation surface.
|
|
832
|
-
- `mcp`: separate MCP integration surface beyond built-in bridge smoke.
|
|
833
|
-
- `semSearch`: semantic index state dependent.
|
|
834
|
-
- `recordScreen`: desktop capture dependency outside terminal smoke.
|
|
835
|
-
- `webSearch`: network/search dependent.
|
|
836
|
-
- `webFetch`: network dependent.
|
|
837
|
-
|
|
838
|
-
Adding a registry entry requires adding it to the required or excluded list with rationale. `ls` is currently excluded from the required one-prompt matrix because 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`.
|
|
839
|
-
|
|
840
|
-
## Platform command rendering
|
|
841
|
-
|
|
842
|
-
Scenario commands are not raw shell strings. The runner renders commands per target:
|
|
843
|
-
|
|
844
|
-
- `posix` for macOS and Ubuntu.
|
|
845
|
-
- `powershell` for Windows native.
|
|
846
|
-
|
|
847
|
-
Scenario shape:
|
|
848
|
-
|
|
849
|
-
```js
|
|
850
|
-
{
|
|
851
|
-
id: "cursor-native-visual-matrix",
|
|
852
|
-
requires: ["cursor-auth", "pty", "packed-install"],
|
|
853
|
-
promptTemplate: "... <platform-command:shellSmoke> ...",
|
|
854
|
-
commands: {
|
|
855
|
-
shellSmoke: {
|
|
856
|
-
posix: "printf 'cursor visual smoke\\n'",
|
|
857
|
-
powershell: "Write-Output 'cursor visual smoke'",
|
|
858
|
-
},
|
|
859
|
-
},
|
|
860
|
-
assertions: ["final-marker", "required-cards", "jsonl-tools"],
|
|
861
|
-
}
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
The renderer owns quoting, path normalization, environment assignment, and archive packaging.
|
|
865
|
-
|
|
866
938
|
## Security and redaction
|
|
867
939
|
|
|
868
|
-
The runner must scan every artifact and fail on:
|
|
940
|
+
The runner must binary-safe scan every bounded regular artifact file, including transport-excluded sensitive names and unknown extensions, and fail closed when a file exceeds the scan cap, cannot be scanned, or is non-regular. It never follows non-regular entries or transports sensitive filenames. Non-artifact infrastructure (`node_modules/` and `.git/`) is pruned. The workspace-root `.platform-artifact-bundle.gz` spill is outside scenario artifact roots and is ignored by Git. It fails on:
|
|
869
941
|
|
|
870
942
|
- the literal `CURSOR_API_KEY` value;
|
|
871
943
|
- bearer tokens;
|
|
@@ -877,154 +949,18 @@ The runner must scan every artifact and fail on:
|
|
|
877
949
|
|
|
878
950
|
Bridge diagnostics may include safe tool names and correlation IDs only.
|
|
879
951
|
|
|
880
|
-
## Implementation phases
|
|
881
|
-
|
|
882
|
-
### Phase 0: plan-only branch state
|
|
883
|
-
|
|
884
|
-
Create this plan on `feat/crabbox-platform-smoke`. Do not implement code in this phase.
|
|
885
|
-
|
|
886
|
-
### Phase 1: dependency spike
|
|
887
|
-
|
|
888
|
-
Verify `node-pty` and ConPTY on every target before committing the dependency.
|
|
889
|
-
|
|
890
|
-
Exit criteria:
|
|
891
|
-
|
|
892
|
-
- node-pty self-test passes on macOS;
|
|
893
|
-
- node-pty self-test passes on Ubuntu local-container;
|
|
894
|
-
- node-pty self-test passes on Windows native Node 24.
|
|
895
|
-
|
|
896
|
-
### Phase 2: config and doctor
|
|
897
|
-
|
|
898
|
-
Add config, CLI skeleton, doctor, and npm scripts.
|
|
899
|
-
|
|
900
|
-
Exit criteria:
|
|
901
|
-
|
|
902
|
-
```bash
|
|
903
|
-
npm run smoke:platform:doctor
|
|
904
|
-
```
|
|
905
|
-
|
|
906
|
-
passes only when all required local setup exists.
|
|
907
|
-
|
|
908
|
-
### Phase 3: target session manager
|
|
909
|
-
|
|
910
|
-
Implement Crabbox target lifecycle for all three targets.
|
|
911
|
-
|
|
912
|
-
Exit criteria:
|
|
913
|
-
|
|
914
|
-
- each target can acquire/warm;
|
|
915
|
-
- each target can sync;
|
|
916
|
-
- each target can run `node --version`;
|
|
917
|
-
- each target can package/download a trivial artifact;
|
|
918
|
-
- each target can stop/cleanup;
|
|
919
|
-
- one lease per target session.
|
|
920
|
-
|
|
921
|
-
### Phase 4: `platform-build`
|
|
922
|
-
|
|
923
|
-
Implement build/package/install suite.
|
|
924
|
-
|
|
925
|
-
Exit criteria: `platform-build` passes on all targets through `smoke:platform:all -- --suite platform-build` without live Cursor calls.
|
|
926
|
-
|
|
927
|
-
### Phase 5: PTY capture and host render
|
|
928
|
-
|
|
929
|
-
Implement PTY/ConPTY capture and host-side xterm/Playwright render.
|
|
930
|
-
|
|
931
|
-
Exit criteria:
|
|
932
|
-
|
|
933
|
-
- ANSI capture works on all targets;
|
|
934
|
-
- host render writes HTML, full PNG, and final viewport PNG;
|
|
935
|
-
- visual evidence detector can capture fixture evidence screenshots.
|
|
936
|
-
|
|
937
|
-
### Phase 6: native visual matrix
|
|
938
|
-
|
|
939
|
-
Implement one-call native matrix.
|
|
940
|
-
|
|
941
|
-
Exit criteria:
|
|
942
|
-
|
|
943
|
-
- all required native visual evidence screenshots are captured on every target;
|
|
944
|
-
- JSONL assertions pass on every target;
|
|
945
|
-
- Cursor call budget remains one call per target.
|
|
946
|
-
|
|
947
|
-
### Phase 7: bridge visual matrix
|
|
948
|
-
|
|
949
|
-
Implement one-call bridge matrix.
|
|
950
|
-
|
|
951
|
-
Exit criteria:
|
|
952
|
-
|
|
953
|
-
- all required bridge visual evidence screenshots are captured on every target;
|
|
954
|
-
- bridge diagnostics assertions pass on every target;
|
|
955
|
-
- JSONL assertions pass on every target.
|
|
956
|
-
|
|
957
|
-
### Phase 8: abort cleanup
|
|
958
|
-
|
|
959
|
-
Implement interrupted bridge run.
|
|
960
|
-
|
|
961
|
-
Exit criteria:
|
|
962
|
-
|
|
963
|
-
- no leftovers on any target;
|
|
964
|
-
- no false success in JSONL;
|
|
965
|
-
- target session stops cleanly.
|
|
966
|
-
|
|
967
|
-
### Phase 9: docs and legacy cleanup
|
|
968
|
-
|
|
969
|
-
Update:
|
|
970
|
-
|
|
971
|
-
- `README.md`
|
|
972
|
-
- `docs/cursor-live-smoke-checklist.md`
|
|
973
|
-
- `docs/cursor-testing-lessons.md`
|
|
974
|
-
- `docs/cursor-native-tool-visual-audit.md`
|
|
975
|
-
|
|
976
|
-
They must state:
|
|
977
|
-
|
|
978
|
-
- required release gate is `npm run smoke:platform:all`;
|
|
979
|
-
- legacy smoke scripts are inner-loop/debug helpers;
|
|
980
|
-
- `tmux` visual smoke is not the canonical cross-platform gate.
|
|
981
|
-
|
|
982
952
|
## Release bar
|
|
983
953
|
|
|
984
|
-
A provider/runtime release is ready only after this exact command passes on the maintainer machine:
|
|
954
|
+
A local provider/runtime release is ready only after this exact command passes on the maintainer machine:
|
|
985
955
|
|
|
986
956
|
```bash
|
|
987
957
|
npm run smoke:platform:all
|
|
988
958
|
```
|
|
989
959
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
## Gate replacement criteria
|
|
993
|
-
|
|
994
|
-
Replace or redesign this platform runner if any of these become true:
|
|
995
|
-
|
|
996
|
-
- Parallels Windows linked clones are unreliable.
|
|
997
|
-
- Windows native cannot run the required ConPTY visual matrix.
|
|
998
|
-
- macOS static SSH localhost cannot run the required PTY visual matrix.
|
|
999
|
-
- Ubuntu local-container cannot run the required PTY visual matrix.
|
|
1000
|
-
- Packed install cannot be tested uniformly across all targets.
|
|
1001
|
-
- Artifact transfer cannot be made uniform across success and failure.
|
|
1002
|
-
- The visual card detector cannot reliably identify required deterministic cards.
|
|
1003
|
-
- The full gate exceeds the fixed Cursor invocation budget.
|
|
1004
|
-
- Node 24 + `node-pty` cannot be made reliable on Windows native.
|
|
960
|
+
Cloud-runtime releases additionally require:
|
|
1005
961
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
Repo-specific pieces:
|
|
1011
|
-
|
|
1012
|
-
- `platform-smoke.config.mjs`
|
|
1013
|
-
- expected package name
|
|
1014
|
-
- model IDs
|
|
1015
|
-
- scenario prompts
|
|
1016
|
-
- required visual card matrix
|
|
1017
|
-
- final markers
|
|
1018
|
-
|
|
1019
|
-
Reusable pieces:
|
|
1020
|
-
|
|
1021
|
-
- Crabbox target session manager
|
|
1022
|
-
- PTY/ConPTY capture
|
|
1023
|
-
- host-side ANSI render
|
|
1024
|
-
- artifact manifest writer
|
|
1025
|
-
- JSONL parser
|
|
1026
|
-
- visual evidence detector
|
|
1027
|
-
- process cleanup checker
|
|
1028
|
-
- target doctor
|
|
962
|
+
```bash
|
|
963
|
+
npm run smoke:cloud
|
|
964
|
+
```
|
|
1029
965
|
|
|
1030
|
-
|
|
966
|
+
`smoke:platform:all` runs doctor first and then all required local targets and suites in one full gate execution.
|