diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eeb12a8..ed4c7cc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,6 +29,16 @@ jobs: - run: bun install --frozen-lockfile + - name: Validate release tag + if: startsWith(github.ref, 'refs/tags/v') + run: | + VERSION=$(node -p "require('./packages/cli/package.json').version") + if [ "$GITHUB_REF_NAME" != "v$VERSION" ]; then + echo "release tag $GITHUB_REF_NAME does not match package version $VERSION" >&2 + exit 1 + fi + echo "RELEASE_VERSION=$VERSION" >> "$GITHUB_ENV" + - run: bun run typecheck - name: Install desktop test dependencies @@ -63,6 +73,10 @@ jobs: - run: bun run build + - name: Install npm with trusted publishing support + if: startsWith(github.ref, 'refs/tags/v') + run: npm install --global npm@11.5.1 + - name: Upload sourcemaps to Sentry if: startsWith(github.ref, 'refs/tags/v') env: @@ -74,10 +88,9 @@ jobs: echo "SENTRY_AUTH_TOKEN not set; skipping" exit 0 fi - VERSION=$(node -p "require('./packages/cli/package.json').version") if ! { npx --yes @sentry/cli sourcemaps inject packages/cli/dist && - npx --yes @sentry/cli sourcemaps upload --release "picklab@$VERSION" packages/cli/dist + npx --yes @sentry/cli sourcemaps upload --release "picklab@$RELEASE_VERSION" packages/cli/dist }; then echo "::warning::Sentry sourcemap upload failed; continuing release" fi @@ -85,11 +98,21 @@ jobs: - name: Publish @pickforge/picklab if: startsWith(github.ref, 'refs/tags/v') working-directory: packages/cli - run: npm publish --access public --provenance + run: | + if npm view "@pickforge/picklab@$RELEASE_VERSION" version >/dev/null 2>&1; then + echo "@pickforge/picklab@$RELEASE_VERSION is already published; skipping" + else + npm publish --access public --provenance + fi - name: Create GitHub release if: startsWith(github.ref, 'refs/tags/v') env: GH_TOKEN: ${{ github.token }} RELEASE_TAG: ${{ github.ref_name }} - run: gh release create "$RELEASE_TAG" --generate-notes + run: | + if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then + echo "GitHub release $RELEASE_TAG already exists; skipping" + else + gh release create "$RELEASE_TAG" --draft --generate-notes + fi diff --git a/AGENTS.md b/AGENTS.md index b1fb2ef..b7ec382 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,14 +49,15 @@ Repo-local guide for agents working in PickLab. internal/release changes, what was tested, what was not tested yet, and known blockers. At release time, use it to polish the generated GitHub release description, then reset the draft. -- Bump `packages/cli/package.json` to the new version, land on `main`, tag - `vX.Y.Z`, push the tag. CI runs the full suite, publishes - `@pickforge/picklab` to npm, and creates the GitHub release — both go live - without manual steps, so make sure `main` is truly ready before tagging. -- The GitHub release description is the single source of release notes - (`--generate-notes` drafts it; edit it after if the generated list reads - poorly). pickforge.dev/picklab shows the latest release via the GitHub API — - no website change needed for a normal release. +- Bump every workspace package manifest and `bun.lock` to the new version, land + on `main`, tag `vX.Y.Z`, and push the tag. CI validates the tag/package match, + runs the full suite, publishes `@pickforge/picklab` to npm, and creates a draft + GitHub release. Make sure `main` is truly ready before tagging because npm goes + live without a manual gate. +- The GitHub release description is the single source of release notes. A human + polishes the generated draft from `docs/releases/UNRELEASED.md` and publishes + it; pickforge.dev/picklab then shows it via the GitHub API. Reset UNRELEASED + after publication. No website change is needed for a normal release. - Only touch `landing-page` (`src/pages/products.ts`) when the install story or positioning changes. ## Workspace policy diff --git a/bun.lock b/bun.lock index ddb745b..52d4a46 100644 --- a/bun.lock +++ b/bun.lock @@ -14,21 +14,21 @@ }, "packages/agent-installers": { "name": "@pickforge/picklab-agent-installers", - "version": "0.1.0", + "version": "0.2.0", "dependencies": { "@pickforge/picklab-core": "*", }, }, "packages/android": { "name": "@pickforge/picklab-android", - "version": "0.1.0", + "version": "0.2.0", "dependencies": { "@pickforge/picklab-core": "*", }, }, "packages/browser": { "name": "@pickforge/picklab-browser", - "version": "0.1.0", + "version": "0.2.0", "dependencies": { "@pickforge/picklab-core": "*", "@pickforge/picklab-desktop-linux": "*", @@ -37,7 +37,7 @@ }, "packages/cli": { "name": "@pickforge/picklab", - "version": "0.1.4", + "version": "0.2.0", "bin": { "picklab": "dist/picklab.js", "picklab-mcp": "dist/picklab-mcp.js", @@ -60,18 +60,18 @@ }, "packages/core": { "name": "@pickforge/picklab-core", - "version": "0.1.0", + "version": "0.2.0", }, "packages/desktop-linux": { "name": "@pickforge/picklab-desktop-linux", - "version": "0.1.0", + "version": "0.2.0", "dependencies": { "@pickforge/picklab-core": "*", }, }, "packages/mcp-server": { "name": "@pickforge/picklab-mcp-server", - "version": "0.1.4", + "version": "0.2.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.17.0", "@pickforge/picklab-android": "*", diff --git a/docs/releases/UNRELEASED.md b/docs/releases/UNRELEASED.md index 0678d90..0ce96e3 100644 --- a/docs/releases/UNRELEASED.md +++ b/docs/releases/UNRELEASED.md @@ -1,338 +1,69 @@ # Unreleased -Working draft for the next PickLab release. Keep this current while PRs land. -At release time, use it to polish the generated GitHub release description, -then reset this file. +Working draft for PickLab v0.2.0. Use this to polish the generated GitHub +release description, then reset it after the release is published. ## User-facing changes -- `desktop_launch` now points `WAYLAND_DISPLAY` at a non-existent socket (and - strips `WAYLAND_SOCKET`), so GTK/Qt/Electron/Flutter apps always fall back - to X11 and render inside the isolated lab display instead of opening on the - user's real Wayland desktop (where driving them moved the real cursor). -- Normal `--vnc` sessions now launch x11vnc with `-viewonly`, so observation is - server-enforced read-only. `--vnc-control` provides an explicit writable path - when a human must enter a password, API key, or OTP directly into the lab app; - it does not yet coordinate with agent input. Loopback binding (`-localhost`), - `-shared`, `-forever`, and no-password (`-nopw`) behavior is unchanged. -- New desktop input primitives on both the CLI and the MCP server - (pickforge/picklab#22): mouse move/hover (`desktop move ` / - `desktop_move`), wheel scroll (`desktop scroll ` / - `desktop_scroll`, integer wheel steps, positive Y down / negative Y up, - positive X right / negative X left, optional pointer position first), - drag (`desktop drag ` / `desktop_drag` with - optional button and duration), and double click - (`desktop double-click ` / `desktop_double_click` with optional - button and click interval). All are argv-array xdotool calls with - validated coordinates, buttons, deltas, and timings — no shell. -- `picklab session create --type browser` and the MCP `session_create` tool can - now create isolated headed Chrome/Chromium sessions. CLI and MCP status, - single-session destroy, and destroy-all include browser sessions. -- `picklab watch [--session ]` now lazily attaches a supported host VNC - client to any running desktop-capable session. The server remains - loopback-only and read-only; closing the viewer leaves VNC, Xvfb, and the - session running. Zero/ambiguous session selection fails with actionable - guidance, and headless/missing-client hosts receive the endpoint plus - install and SSH-tunnel instructions without opening a window. -- Viewer launch defaults to `viewer.mode: "manual"` and can be set to `"auto"` - in global/project config. `session create --viewer` and `--no-viewer` are - one-shot overrides. Creation returns after the client starts instead of - waiting for its window to close, reports attach failures alongside the - created session, rejects explicit viewer plus writable VNC, and suppresses - auto-viewing for writable VNC. MCP status and session resources report - viewer endpoint/readiness but never launch a host GUI. -- New static `picklab-browser` agent entry runs `picklab browser devtools-mcp`. - It discovers exactly one live browser session for the current project on - every connection, so browser recreation needs no endpoint config changes. - The command does not accept a browser URL or websocket endpoint. +- Added isolated headed Chrome/Chromium sessions, including CLI and MCP session + lifecycle support and a static `picklab-browser` DevTools MCP entry. +- Added `picklab watch` plus configurable manual/automatic VNC viewer attachment + for running desktop-capable sessions. VNC remains loopback-only and read-only + by default; writable access requires the explicit `--vnc-control` path. +- Added desktop mouse move, scroll, drag, and double-click controls to both the + CLI and MCP server. +- Added end-to-end computer-use evidence recording for desktop, Android, and + browser actions. Reports include a sanitized action timeline and optional + screenshot filmstrip, with bounded storage, retention, and MCP resources. +- Strengthened secret redaction across logs, browser diagnostics, telemetry, + UI trees, logcat, and evidence, including cookies, authorization credentials, + JWTs, credential-bearing URLs, session identifiers, OTP/CSRF values, and + Chrome DevTools capability URLs. +- Fixed desktop app launches on Wayland hosts so applications reliably render + inside the isolated X11 lab display. +- Improved Linux screenshot capture by preferring `maim` when available and + suppressing noisy ImageMagick `import` stderr. ## Internal/release changes -- Routed dead-session reaping through the desktop, Android, and browser typed - teardown owners. Core now owns only registry/liveness/retry/evidence policy, - eliminating its duplicate PID and browser-profile stop implementation. CLI - and MCP creation compose all owners; direct package creation reaps its own - runtime type. -- Stabilized the browser Xvfb cancellation regression test by waiting for the - fake process's complete PID/display marker instead of treating file creation - as publication. This removes the full-suite/coverage race that could abandon - the in-flight create and cascade into a misleading ownership-handoff failure. -- Strengthened `redactSecrets` (pickforge/picklab#20): Cookie/Set-Cookie - values pair by pair, including balanced double/single-quoted values and - apostrophes in unquoted values, while cookie attributes like - `Path`/`SameSite` and XML/JSON embedding delimiters survive; complete - `Authorization:` header credentials for any scheme (Basic, Bearer, and - Digest with quoted parameters); bare JWTs; credential-bearing URL query - values (`token`/`session`/`code`/`auth`-like names); semicolon path - parameters such as `;jsessionid=...`; bare `session`/`sessionId` - assignments and JSON fields (session-adjacent metadata like `sessionCount` - untouched); OTP/CSRF assignments; and Chrome DevTools websocket capability - URLs/GUID paths. Existing consumers (logcat, ui-tree, MCP resources, relay - diagnostics, telemetry) pick this up automatically. -- Added fail-closed structured evidence sanitizers to - `@pickforge/picklab-core` (`evidence-sanitize.ts`) for the upcoming - computer-use evidence journal: `sanitizeUrlForEvidence` (origin + path - only, semicolon path parameters stripped, `blob:` URLs reduced to - `blob:` + inner origin), `sanitizeErrorText` (redacted then bounded), `sanitizeTypedValue` - (length + allowlisted input type only), `sanitizeActionTarget` (per-field - allowlist; unknown fields dropped), and `sanitizeNetworkFailure` - (method/origin-path/status/resource type/timing/sanitized error only — - never headers, bodies, or query). MCP computer-use producers now consume - these sanitizers before appending actions. -- Added the computer-use evidence storage foundation to - `@pickforge/picklab-core`. New `evidence.ts` provides - a session-scoped active-run pointer claimed with an atomic `wx` protocol. The - winner stamps a claim carrying its verifiable owner identity (PID + - `/proc` start ticks) at creation time, then creates the run and atomically - publishes (temp + rename) the full pointer over its own claim, confirming it is - the published owner before returning; racing peers adopt the single winner's - run and never steal a claim from a live owner (only a provably dead owner, or - an owner-unknown empty claim past a short grace, is reclaimed), so no orphan - run dirs result. If run creation succeeds but publication/verification fails, - the just-created run is finalized (`failed`) so no permanent running orphan is - left. Pointer resolution classifies a `running` run whose recorded owner is - dead or PID-reused as stale/recoverable rather than active. The append-only - `actions.jsonl` journal uses a recoverable owner-stamped cross-process lock to - serialize torn-tail repair, cap accounting, and one verified `O_APPEND` write - per bounded record (never rewriting the manifest); reads are deterministic and - tolerate only a torn final line, which the next append removes before writing. - A 100 MiB per-run cap is enforced cumulatively - from the run's real on-disk bytes (journal + artifacts, symlinks never - followed), so it holds across many appends and processes; it emits exactly one - truncation marker after which bounded metadata-only actions continue. That - marker uses the same recoverable-claim protocol as the pointer: the atomic - `wx` sentinel winner stamps its owner identity, appends the marker, then - atomically commits the sentinel (temp + rename). A crash or append failure - between claim and commit no longer blocks truncation forever — a provably dead - or owner-unknown claim is re-raced (checking the journal first so a marker a - prior writer already committed is never duplicated), and an append error clears - its own claim; a committed sentinel stays idempotent. A retention primitive - keeps the latest 20 - finalized evidence runs, binding every removal to the directory a manifest - physically lives in and re-verifying that manifest immediately before `rm`, so - a spoofed or corrupt `runId` can never redirect a deletion at a running or - another run's directory; running/active and legacy runs are never pruned. - `RunManifest` gained optional, backward-compatible `evidenceVersion`, - `actionLog`, and `evidenceTruncated` fields; `createRun({ evidence: true })` - stamps them and seeds the empty journal, so plain screenshot runs are - unaffected. Config resolution gained `evidence.enabled` (product - configuration, default true) via `isEvidenceEnabled`. -- Added backward-compatible evidence rendering for recorded runs: CLI and MCP - artifact reports now include a deterministically ordered, defensively redacted - action timeline, while legacy runs remain artifact inventories. Evidence runs - can publish an escaped, no-script `report.html` filmstrip with a restrictive - CSP and only confined regular screenshot files. MCP resources expose sorted - action JSON and the static HTML report while rejecting legacy, malformed, - missing, symlinked, swapped, or out-of-run evidence files. Fixed-file resource - reads bind no-follow descriptors to the validated file identity and re-check - the pathname after reading; journal reads/appends also use no-follow opens. - Report publication uses an exclusive temporary file plus atomic rename so - planted symlinks are never followed. -- MCP desktop, Android, and session tools now append sanitized success/failure - actions to one active evidence run per session. Typed values persist only as - length plus allowlisted input type; metadata actions never auto-capture - screenshots. Explicit screenshot tools associate confined PNG paths with the - active journal, while sessions without an active evidence run preserve the - existing one-shot screenshot run. Session destroy finalizes and releases the - run, and dead-session reaping finalizes it as failed. Evidence failures are - redacted, stderr-only, and never change the underlying tool result. -- The browser DevTools relay now correlates `tools/call` requests and responses - into the same session evidence run. It persists only allowlisted target - metadata, typed-value lengths/types, bounded sanitized errors, failed network - request metadata (method, origin/path, status/type/timing/error), and - warning/error console summaries; never request/response bodies, headers, - query strings, userinfo, raw arguments, evaluated code, or typed text. - Explicit inline PNG screenshot results are copied into the run and associated - with their action. Pending calls are closed on relay exit, diagnostic fan-out - is bounded, `evidence.enabled: false` is honored, and all evidence failures - remain redacted and relay-transparent. -- Hosted CI now installs `x11vnc` alongside the other desktop test - dependencies, and the desktop-linux integration suite asserts `x11vnc` is - present when `CI=true` so VNC tests fail loudly instead of silently - skipping on a misconfigured runner. -- Added browser session contracts to `@pickforge/picklab-core`: a `browser` - session type with `BrowserSessionInfo`, capability-based session resolution - (`SessionCapability`, `sessionHasCapability`), and verified process-group stop - primitives (`stopProcessGroupVerified`, `processIdentityMatches`, and friends) - wired into the session reaper and the CLI/MCP browser lifecycle. -- Browser reaping now confirms the recorded browser process group is gone - before stopping VNC/Xvfb helpers or deleting the session record. Reused or - otherwise unconfirmed groups leave dependent helpers and profile data intact - and mark the record as errored for inspection. -- Lazy VNC now persists process-start identity and shares a per-session mutation - lock with desktop/browser destruction. Reuse, status, teardown, and reaping - fail closed for missing or reused identities without signaling unrelated - processes. -- `startXvfb` gained an additive `displayStart` option so browser sessions use - displays from `:200` without contending with desktop sessions from `:90`. -- Added internal `@pickforge/picklab-browser`, owning Chrome/Chromium detection, - a private Xvfb, ephemeral profile, dynamic loopback CDP discovery, scrubbed - environment, PID-identity process-group teardown, status, retryable - partial-failure cleanup, and concurrent-session safety. The DevTools websocket - path/GUID is never persisted. -- Added an exact direct dependency on `chrome-devtools-mcp@1.5.0`. PickLab - validates its installed manifest name, version, declared bin, and confined - real path, then starts that bin directly with Node and a derived loopback - `--browser-url`; runtime `npx`, upstream update checks, and usage statistics - are disabled. -- Added a framing-aware bidirectional NDJSON relay with protocol validation, - arbitrary chunk buffering, exact raw-byte preservation when hooks do not - transform a message, request/response hooks for follow-up coordination, - backpressure, EOF/signal forwarding, bounded hung-child cleanup, exit - propagation, and redacted stderr-only diagnostics. Pending JSON-RPC records - are capped at 16 MiB and diagnostic lines at 64 KiB. The implementation uses - a local typed deferred helper rather than newer runtime Promise APIs, keeping - the upstream-compatible Node 20.19 floor. -- CI and release workflows pin Node `20.19.0`, the advertised minimum that - exercises the relay and upstream package contract. -- The canonical installer enforces the same supported Node branches: - `^20.19`, `^22.12`, or `>=23`. -- CI installs a supported browser and requires the real headed-Chrome integration - suite to execute rather than silently skip. -- SECURITY.md documents the residual same-UID and local-process risks. +- Added a private browser lifecycle package with confined ephemeral profiles, + loopback-only CDP discovery, verified process-group teardown, concurrent + session safety, and conservative dead-session reaping. +- Centralized session lifecycle composition in core and routed dead-session + reaping through typed desktop, Android, and browser teardown owners, removing + duplicate CLI/MCP orchestration and core PID/profile stop implementations. +- Added a framing-aware DevTools NDJSON relay with protocol validation, + backpressure, bounded diagnostics, redacted failures, and evidence hooks. +- Added atomic, crash-recoverable evidence journals, active-run ownership, + truncation markers, report publication, and symlink-safe resource access. +- Hardened Android and evidence cleanup around process identity, atomic writes, + metadata keys, directory traversal cost, and stale ownership recovery. +- Pinned Bun 1.3.12 and Node 20.19.0 in CI/release workflows, moved npm publish + to trusted publishing with npm 11.5.1, added tag/version and retry-safety + guards, and made headed-browser and VNC dependencies explicit in hosted + validation. Tag pushes now create a draft GitHub release for human review. +- Stabilized Xvfb startup cancellation coverage to avoid abandoned browser + creation during full-suite runs. +- Replaced the duplicated repository workspace policy with a pointer to the + canonical workspace instructions. ## Validation ### Tested -- Regression test asserting launched apps get `DISPLAY=` with - Wayland variables unset; full desktop-linux integration suite (Xvfb + - xdotool + xterm) passes. -- `buildVncArgs` exact-argv test updated to require `-viewonly`; hosted-CI - prerequisite assertion verified to fail loudly (not skip) when `CI=true` - and `x11vnc` is absent, and to pass once `x11vnc` is on `PATH`. -- Exact xdotool argv unit tests for move, scroll (direction/ordering/repeat), - drag (button/duration), and double click (button/interval); CLI and MCP - validation tests for out-of-range buttons, deltas, durations, and - intervals; live Xvfb smoke driving move, scroll, drag, and double-click and - asserting the pointer position via `xdotool getmouselocation`. -- Process-group regression tests cover reused PID refusal, stubborn children, - and zombie-only groups. -- `bun run test packages/core` (8 files, 107 passed) and - `bun run typecheck` pass. Core session regressions verify browser-group-first - teardown and fail-closed handling for an unconfirmed browser identity. +- `bun install --frozen-lockfile` - `bun run typecheck` -- `bun run build` for all packages. -- Focused browser/core/desktop/CLI/MCP/security tests: 208 passed / 2 skipped. -- Fake-Chrome lifecycle tests cover private runtime modes, verified CDP HTTP - readiness, create/status/destroy, centralized display-socket liveness, - concurrent displays, crash-after-port, cancellation during Xvfb startup and - record commit, crash/stall cleanup, automatic reaper retry after failed create - or destroy, conservative legacy desktop liveness, symlink-safe profile - confinement, retryable removal failures, capability-URL log redaction with - preserved diagnostics, verified Xvfb PID identity and reuse refusal, - post-SIGTERM group escalation, GUID exclusion, and environment scrubbing. -- Built `picklab` and `picklab-mcp` tests cover browser create, status, individual - destroy, destroy-all, complete session-directory removal, profile removal, and - environment scrubbing. -- Final full coverage suite: 63 files, 705 passed / 2 skipped, all thresholds met. -- Real built-CLI Chrome proof covered create, running status, visible typing and - navigation, screenshot inspection, and destroy; Chrome, Xvfb, the ephemeral - profile, session logs, and the session record were removed. Persisted Chrome - logs contained no DevTools websocket capability URL. -- `bun run typecheck` and `bun run build` pass after rebasing watch onto the - browser lifecycle. The full suite passes 65 files / 737 tests with 2 skipped. -- Focused browser/core/desktop/CLI/MCP/security validation passes 232 tests in - 18 files. Coverage includes browser create/status/destroy, lazy VNC teardown - after verified Chrome-group termination, deterministic ensure/destroy race - ordering, stale-lock breakers, VNC process-identity reuse refusal, profile - confinement, environment scrubbing, manual/auto viewer config, - zero/ambiguous/headless watch behavior, process-safe VNC reuse and endpoint - ownership, asynchronous viewer launch, explicit nonzero/signal failure, - attach-failure reporting, JSON stdout isolation, browser viewer/status - integration, MCP status-only behavior, and secret redaction. -- Real x11vnc + TigerVNC proof attached a host viewer to the isolated display, - confirmed server-enforced `-viewonly`, and verified that closing the viewer - left the PickLab session, VNC server, and Xvfb running. -- Relay slice: `bun run typecheck` and `bun run build` pass. The final focused - browser relay, CLI, and installer command passed 17 files / 161 tests. After - rebasing onto live watch and applying the final review fix, the integrated - full suite passes 70 files / 780 tests with 2 skipped. - Coverage includes exact package/bin/spawn validation, bounded NDJSON and - diagnostic fragmentation, transformations, protocol fail-closed behavior, - IDs/order/cancellation, backpressure, clean/forced exit races, stubborn - child-process errors with held stdin and verified SIGKILL cleanup, genuine - spawn failures with no `exit` event, EOF/signals/hung cleanup, real open-stdin - CLI exit 137 after escalation, - stderr purity, session scoping, static agent entries, installer Node-version - boundaries, required-browser CI prerequisite enforcement, and operation - without native `Promise.withResolvers`. -- A real headed-Chrome + exact upstream `chrome-devtools-mcp@1.5.0` smoke - navigated a local page and verified accessibility snapshot, console, and - network metadata through the built `picklab browser devtools-mcp` command. - The existing real-Chrome lifecycle integration also passed (3 tests). -- Xvfb cancellation regression: 60 focused iterations and 12 parallel - browser + desktop-linux suite iterations pass with a deliberately split - fake startup-marker publication; the browser session suite (25 tests) and - `bun run typecheck` pass. -- Typed reaper teardown: core plus desktop-linux, Android, and browser suites; - CLI/MCP session tests; `bun run typecheck`; and `bun run build` pass. - -- Evidence storage foundation: `bun run typecheck`, `bun run build`, and the - full suite pass (73 files, 895 passed / 2 skipped). New core coverage - (`evidence.ts` 90.97% lines / 83.03% branches / 97.43% - functions) includes real separate-process concurrent appenders losing zero - actions, a real separate-process begin race resolving to one run with no orphan - dirs, an in-process pointer race, a deliberately slow live-winner race proving - a live claimer is never stolen, stale/corrupt/dead-owner pointer recovery, - empty- and dead-claim reclaim, injected pointer-publication failure finalizing - the just-created run, bounded-line rejection, verified full-write behavior, - dead-owner journal-lock recovery, and torn-tail repair before the next append, - cumulative on-disk cap/truncation determinism with injected limits (no 100 MiB - allocation), and — for the durable truncation marker — injected marker-append - failure preserving the committed action without inviting a duplicate retry, - then clearing its claim and recovering; dead-owner and owner-unknown - (empty) sentinel reclaim, no-duplicate recovery when a prior claim already - committed the marker, sentinel-commit failure keeping the marker durable, - committed-sentinel idempotency, a live marker-claim never stolen by a racing - peer, and separate-process coverage proving exactly one marker across four - contending processes plus recovery after a process crashes mid-claim. - Retention of 20 finalized runs while preserving running/active/legacy and - resisting spoofed-`runId`/fake-inflation manifests, and old-manifest list/read - compatibility, are also covered. `bun run test:coverage` passes global - thresholds. -- Evidence rendering/resources: `bun run typecheck` and `bun run build` pass; - the full and coverage suites pass 74 files / 916 passed / 2 skipped. Focused - tests cover deterministic ordering and post-sort step numbers, legacy reports, - corrupt/torn journals, planted secrets, HTML/XSS escaping and CSP, confined - screenshot embedding, action/report resource MIME and listings, and rejection - of symlinked journals, reports, screenshots, run directories, planted report - publication targets, and parent-directory swaps between validation and open. -- MCP evidence instrumentation: `bun run typecheck` and `bun run build` pass; - the full and coverage suites pass 75 files / 928 passed / 2 skipped with all - global thresholds met. Coverage includes sanitized typed actions and - thrown/structured failures, confined screenshot association, - disabled/no-session behavior, evidence-write failure isolation, active-run - reuse, explicit/shared session finalization, in-flight claim coordination, - and dead-session reaping. Two independent changed-HEAD reviews are clean. -- DevTools evidence instrumentation: `bun run typecheck` and `bun run build` - pass; the full and coverage suites pass 76 files / 942 passed / 2 skipped - with all global thresholds met. Focused tests cover request/response - correlation, strict tool/target allowlists, typed/form privacy, URL stripping, - fail-closed JSON-RPC and tool-result errors, pinned-directory inline PNG - association and cap cleanup, failed-network and severity-only console - diagnostics, malformed/unmatched traffic, pending-call closure, disabled - configuration, evidence-write failure isolation, and bounded diagnostics. - Two independent changed-HEAD reviews are clean. -- Final evidence integration: `bun run typecheck` and `bun run build` pass; - the full and coverage suites pass 77 files / 945 passed / 2 skipped with all - global thresholds met. A failed DevTools relay flow produces an automatically - finalized, useful HTML report without persisted typed text, URL query tokens, - headers, bodies, JWTs, CDP capability values, or OTPs. Focused lifecycle tests - cover report publication on explicit destruction and dead-session reaping, - inclusion of the final `session_destroy` action, rejection of mismatched - manifest/pointer identities, and fresh relay-target resolution after browser - recreation. README and security guidance document recording, resources, the - 100 MiB threshold, 20-run retention, opt-out behavior, and unredactable - screenshot pixels. Two independent changed-HEAD reviews are clean. +- `bun run test` (79 files, 958 passed / 2 skipped) +- `bun run test:coverage` (79 files, 958 passed / 2 skipped; all thresholds met) +- `bun run build` ### Not tested yet - Platform smoke checks outside Linux. -- Live hosted CI run with `x11vnc` actually installed (validated locally via - fake binaries and a `CI=true` dry run only). - Live remote SSH-tunnel smoke test. +- Tag-triggered npm publish and draft-release creation (runs only after merge and + tag push). ### Release blockers -- None known for the final evidence integration slice. +- None known. diff --git a/packages/agent-installers/package.json b/packages/agent-installers/package.json index e602371..cb0b7ee 100644 --- a/packages/agent-installers/package.json +++ b/packages/agent-installers/package.json @@ -1,6 +1,6 @@ { "name": "@pickforge/picklab-agent-installers", - "version": "0.1.0", + "version": "0.2.0", "private": true, "description": "Codex, Claude Code, Cursor, and custom agent registration for PickLab", "type": "module", diff --git a/packages/android/package.json b/packages/android/package.json index 35e0989..fc87910 100644 --- a/packages/android/package.json +++ b/packages/android/package.json @@ -1,6 +1,6 @@ { "name": "@pickforge/picklab-android", - "version": "0.1.0", + "version": "0.2.0", "private": true, "description": "AVD, emulator, ADB, UIAutomator, and logcat orchestration for PickLab", "type": "module", diff --git a/packages/browser/package.json b/packages/browser/package.json index 43a3325..5656aa9 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -1,6 +1,6 @@ { "name": "@pickforge/picklab-browser", - "version": "0.1.0", + "version": "0.2.0", "private": true, "description": "Isolated headed Chrome/Chromium browser sessions for PickLab", "type": "module", diff --git a/packages/cli/package.json b/packages/cli/package.json index 5651727..67b142b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@pickforge/picklab", - "version": "0.1.4", + "version": "0.2.0", "description": "Native app and Android emulator automation for AI coding agents", "type": "module", "license": "MIT", diff --git a/packages/core/package.json b/packages/core/package.json index 7cc778b..db7a653 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@pickforge/picklab-core", - "version": "0.1.0", + "version": "0.2.0", "private": true, "description": "Config, sessions, artifacts, manifests, and process supervision for PickLab", "type": "module", diff --git a/packages/desktop-linux/package.json b/packages/desktop-linux/package.json index 18a922b..e4f6b75 100644 --- a/packages/desktop-linux/package.json +++ b/packages/desktop-linux/package.json @@ -1,6 +1,6 @@ { "name": "@pickforge/picklab-desktop-linux", - "version": "0.1.0", + "version": "0.2.0", "private": true, "description": "Xvfb, VNC, window, input, and screenshot automation for PickLab", "type": "module", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index cc94d12..90a6152 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "@pickforge/picklab-mcp-server", - "version": "0.1.4", + "version": "0.2.0", "private": true, "description": "MCP server implementation for PickLab", "type": "module",