diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 782a8c6..f3f1164 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,9 @@ jobs: - name: Build run: mise run build + - name: Packaging smoke + run: mise run install-smoke + # macOS compilation and static-analysis counterpart to the Ubuntu quality # gates above. Tests are excluded because the macOS GitHub Actions runner # has pre-existing issues with PTY spawning and Unix domain sockets that diff --git a/README.md b/README.md index 585e16d..e56dab6 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,60 @@ It is built for agent workflows that need both semantic state and visual artifac ## Installation -### Global installation +`agent-terminal` currently supports Node `24.x`. +Released builds install from npm. For prerelease/private use, the guaranteed install path is a built tarball; direct GitHub installs are best-effort and may still fail in some environments. + +### npm registry installation + +#### Global installation ```bash npm install -g agent-terminal agent-terminal version --json ``` -### Project installation +#### Project installation ```bash npm install agent-terminal ./node_modules/.bin/agent-terminal version --json ``` +### Direct GitHub installation + +```bash +npm install -g github:coder/agent-terminal +agent-terminal version --json +``` + +GitHub installs attempt to build from source via npm's `prepare` hook. +Use this when you want the latest default-branch snapshot and your npm/git-dependency environment can build native dependencies cleanly. + +Today, the guaranteed prerelease path is still the built tarball route below. +The repository's install smoke now treats tarball install as the required path and records the current git-install caveat separately, because native dependencies such as `node-pty` can still fail during npm's git-dependency flow in some environments. + +If your shell setup injects `mise activate` (or similar trust-checked tooling) into npm lifecycle subprocesses, trust the checkout path first or use the tarball route below. + +### Private tarball installation + +When you need a deterministic prerelease artifact before the package is published, prefer a built tarball: + +```bash +TARBALL_DIR=$(mktemp -d) +npm ci +npm run pack:private -- --pack-destination "$TARBALL_DIR" + +INSTALL_PREFIX=$(mktemp -d) +npm install -g --prefix "$INSTALL_PREFIX" "$TARBALL_DIR"/agent-terminal-*.tgz +"$INSTALL_PREFIX"/bin/agent-terminal version --json +"$INSTALL_PREFIX"/bin/agent-terminal --home "$(mktemp -d)" doctor --json +``` + +`npm run pack:private` always rebuilds `dist/` before packing, so the tarball matches the private artifact reviewers should install. +Keep the tarball route as the guaranteed private-distribution fallback even when GitHub installs are convenient. + +If `doctor --json` reports a missing Playwright browser cache on a fresh machine, run `npx playwright install chromium` once before renderer-backed workflows. + ## Quick start ```bash @@ -220,7 +260,7 @@ Useful shortcuts: npm run verify ``` -That runs formatting, linting, typechecking, unit/e2e tests, and the production build. +That runs formatting, linting, typechecking, unit/e2e tests, the production build, and packaging/install smoke coverage for the required tarball route plus the current git-dependency behavior/caveat check. For contributor workflow and release hygiene, see [`docs/CONTRIBUTING.md`](./docs/CONTRIBUTING.md) and [`docs/RELEASE-PROCESS.md`](./docs/RELEASE-PROCESS.md). ## Design docs diff --git a/docs/RELEASE-PROCESS.md b/docs/RELEASE-PROCESS.md index 1e6e784..1f717bc 100644 --- a/docs/RELEASE-PROCESS.md +++ b/docs/RELEASE-PROCESS.md @@ -17,6 +17,8 @@ Run the full repo validation command: npm run verify ``` +That command now includes the tarball packaging smoke plus a git-install caveat check, so release candidates exercise the guaranteed private-distribution path and record the current git-dependency behavior before publish. + If the public skill changed, also run: ```bash diff --git a/dogfood/CATALOG.md b/dogfood/CATALOG.md index e8f45bc..a343647 100644 --- a/dogfood/CATALOG.md +++ b/dogfood/CATALOG.md @@ -5,18 +5,19 @@ Paths below are relative to the repository root. ## Canonical scenarios -| Scenario | What it demonstrates | Bundle | -| ---------------- | -------------------------------------------------------------------------------- | ---------------------------------------- | -| Hello prompt | Basic lifecycle, wait, screenshot, and recording flow | `dogfood/20260322-dogfood-hello-prompt/` | -| Run command | The higher-level `run` workflow for shell setup and command injection | `dogfood/run-command/` | -| Color rendering | ANSI color capture and screenshot review | `dogfood/20260322-dogfood-color/` | -| Alternate screen | Entering and leaving an alt-screen TUI while preserving the main screen | `dogfood/20260322-dogfood-alt-screen/` | -| Resize | PTY resizing and stable-screen verification | `dogfood/20260322-dogfood-resize/` | -| Scrollback | Scrollback-aware snapshots, screenshots, and recording export | `dogfood/20260322-dogfood-scrollback/` | -| Unicode | Unicode rendering plus snapshot/export review | `dogfood/20260322-dogfood-unicode/` | -| LazyVim | A real TUI scenario that exercises editor startup and reviewer-visible artifacts | `dogfood/20260322-lazyvim-scenario/` | -| Public skill | The shipped `skills/agent-terminal/` workflow and documentation surface | `dogfood/20260327-public-skill/` | -| Config parity | Configuration/profile behavior checks that remain useful as a standing scenario | `dogfood/week5-config-parity/` | +| Scenario | What it demonstrates | Bundle | +| ---------------- | ----------------------------------------------------------------------------------- | ---------------------------------------- | +| Hello prompt | Basic lifecycle, wait, screenshot, and recording flow | `dogfood/20260322-dogfood-hello-prompt/` | +| Run command | The higher-level `run` workflow for shell setup and command injection | `dogfood/run-command/` | +| Color rendering | ANSI color capture and screenshot review | `dogfood/20260322-dogfood-color/` | +| Alternate screen | Entering and leaving an alt-screen TUI while preserving the main screen | `dogfood/20260322-dogfood-alt-screen/` | +| Resize | PTY resizing and stable-screen verification | `dogfood/20260322-dogfood-resize/` | +| Scrollback | Scrollback-aware snapshots, screenshots, and recording export | `dogfood/20260322-dogfood-scrollback/` | +| Unicode | Unicode rendering plus snapshot/export review | `dogfood/20260322-dogfood-unicode/` | +| LazyVim | A real TUI scenario that exercises editor startup and reviewer-visible artifacts | `dogfood/20260322-lazyvim-scenario/` | +| Public skill | The shipped `skills/agent-terminal/` workflow and documentation surface | `dogfood/20260327-public-skill/` | +| Install flows | Pre-public tarball install proof plus the current local git-install caveat evidence | `dogfood/install-flows/` | +| Config parity | Configuration/profile behavior checks that remain useful as a standing scenario | `dogfood/week5-config-parity/` | ## Validation and release gates diff --git a/dogfood/install-flows/README.md b/dogfood/install-flows/README.md new file mode 100644 index 0000000..c7b7b1c --- /dev/null +++ b/dogfood/install-flows/README.md @@ -0,0 +1,32 @@ +# Install flow proof bundle + +This bundle captures a 2026-04-07 review pass for the prerelease install paths. + +## Environment + +- Node runtime used for installed-binary checks: v24.14.0 +- npm used for packaging/install commands: 11.9.0 +- Tarball artifact: /home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball-artifact/agent-terminal-0.1.0.tgz +- Git source revision: 4443b7a66dcf91e9798773abdf363eda746358aa +- Git source URL: git+file:///tmp/tmp.6ZtZ24ucrQ/src#4443b7a66dcf91e9798773abdf363eda746358aa + +## What is included + +### Tarball route (`tarball/`) + +- `pack.json` records the built package contents. +- `install.log`, `version.json`, and `doctor.json` capture the successful install + verification outputs. +- `install.png`, `version.png`, and `doctor.png` are reviewer-facing screenshots. +- `install-flow.webm` and `install-flow.cast` are the corresponding terminal recordings. + +### Git route (`git/`) + +- `install.log` captures a representative direct git install attempt from this workspace. +- `install.png` and `install-flow.webm` render that transcript for review. +- `blocker.md` documents why this workspace could not produce installed-binary `version --json` / `doctor --json` outputs for the git route. + +## Important review note + +The tarball route is the fully verified private-distribution path in this bundle. +The git route evidence is intentionally a blocker transcript rather than a successful install proof: the smoke check now accepts a narrow family of known git-install caveats in environments like this one, while keeping the tarball route as the required passing path. +That caveat is also reflected in the updated installation docs, which keep the tarball route as the guaranteed fallback. diff --git a/dogfood/install-flows/commands.sh b/dogfood/install-flows/commands.sh new file mode 100755 index 0000000..88c8f0f --- /dev/null +++ b/dogfood/install-flows/commands.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Tarball proof commands used: +# MISE_TRUSTED_CONFIG_PATHS="$PWD:/tmp:$HOME/.npm" npx -y npm@11.9.0 run build +# MISE_TRUSTED_CONFIG_PATHS="$PWD:/tmp:$HOME/.npm" npx -y npm@11.9.0 pack --json --ignore-scripts --pack-destination dogfood/install-flows/tarball-artifact +# MISE_TRUSTED_CONFIG_PATHS="$PWD:/tmp:$HOME/.npm" npx -y npm@11.9.0 install -g --prefix +# PATH="$(dirname "/home/coder/.npm/_npx/387698761821791d/node_modules/node/bin/node"):$PATH" /bin/agent-terminal version --json +# PATH="$(dirname "/home/coder/.npm/_npx/387698761821791d/node_modules/node/bin/node"):$PATH" /bin/agent-terminal --home doctor --json +# /home/coder/.npm/_npx/387698761821791d/node_modules/node/bin/node --import tsx ./src/cli/main.ts create/run/wait/screenshot/record export ... +# +# Git proof commands used: +# MISE_TRUSTED_CONFIG_PATHS="$PWD:/tmp:$HOME/.npm" npx -y npm@11.9.0 install -g --prefix "git+file:///tmp/tmp.6ZtZ24ucrQ/src#4443b7a66dcf91e9798773abdf363eda746358aa" +# /home/coder/.npm/_npx/387698761821791d/node_modules/node/bin/node --import tsx ./src/cli/main.ts create/run/wait/screenshot/record export ... +# +# See tarball/install-step.sh, tarball/version-step.sh, tarball/doctor-step.sh, +# and git/install-step.sh for the exact terminal-display commands captured in the screenshots/video. diff --git a/dogfood/install-flows/git-source-path.txt b/dogfood/install-flows/git-source-path.txt new file mode 100644 index 0000000..a5ba0a2 --- /dev/null +++ b/dogfood/install-flows/git-source-path.txt @@ -0,0 +1 @@ +/tmp/tmp.6ZtZ24ucrQ/src diff --git a/dogfood/install-flows/git-source-revision.txt b/dogfood/install-flows/git-source-revision.txt new file mode 100644 index 0000000..0152a19 --- /dev/null +++ b/dogfood/install-flows/git-source-revision.txt @@ -0,0 +1 @@ +4443b7a66dcf91e9798773abdf363eda746358aa diff --git a/dogfood/install-flows/git-source-url.txt b/dogfood/install-flows/git-source-url.txt new file mode 100644 index 0000000..ec27a1a --- /dev/null +++ b/dogfood/install-flows/git-source-url.txt @@ -0,0 +1 @@ +git+file:///tmp/tmp.6ZtZ24ucrQ/src#4443b7a66dcf91e9798773abdf363eda746358aa diff --git a/dogfood/install-flows/git/agent-terminal-home.txt b/dogfood/install-flows/git/agent-terminal-home.txt new file mode 100644 index 0000000..af236fb --- /dev/null +++ b/dogfood/install-flows/git/agent-terminal-home.txt @@ -0,0 +1 @@ +/tmp/tmp.vQk7Eo2uSg diff --git a/dogfood/install-flows/git/blocker.md b/dogfood/install-flows/git/blocker.md new file mode 100644 index 0000000..5bf9ef6 --- /dev/null +++ b/dogfood/install-flows/git/blocker.md @@ -0,0 +1,7 @@ +# Git install blocker in this workspace + +The direct git install transcript in `install.log` is a representative run from this workspace. +It fails before the installed binary exists because npm's git-dependency preparation path is still fragile here: in this capture, the temp clone could not resolve `tsc`/dependency state cleanly during `npm run build`, though related runs in this environment have also failed in native-dependency paths such as `node-pty`. + +Because the install never produced a binary, there are no `version --json` or `doctor --json` outputs for the git route in this local proof bundle. +The supported fallback proof is the tarball route, and the README installation section documents the tarball path as the guaranteed private-distribution route. diff --git a/dogfood/install-flows/git/create.json b/dogfood/install-flows/git/create.json new file mode 100644 index 0000000..164e12e --- /dev/null +++ b/dogfood/install-flows/git/create.json @@ -0,0 +1,12 @@ +{ + "ok": true, + "command": "create", + "timestamp": "2026-04-07T20:31:04.783Z", + "result": { + "sessionId": "01KNMT8ERRG69NVF3QF7A0M4PN", + "createdAt": "2026-04-07T20:31:03.962Z", + "cols": 140, + "rows": 40, + "shell": "/bin/bash" + } +} diff --git a/dogfood/install-flows/git/destroy.json b/dogfood/install-flows/git/destroy.json new file mode 100644 index 0000000..a8c59f8 --- /dev/null +++ b/dogfood/install-flows/git/destroy.json @@ -0,0 +1,9 @@ +{ + "ok": true, + "command": "destroy", + "timestamp": "2026-04-07T20:31:14.846Z", + "result": { + "sessionId": "01KNMT8ERRG69NVF3QF7A0M4PN", + "destroyed": true + } +} diff --git a/dogfood/install-flows/git/initial-wait.json b/dogfood/install-flows/git/initial-wait.json new file mode 100644 index 0000000..841ea51 --- /dev/null +++ b/dogfood/install-flows/git/initial-wait.json @@ -0,0 +1,12 @@ +{ + "ok": true, + "command": "wait", + "timestamp": "2026-04-07T20:31:07.009Z", + "result": { + "matched": true, + "timedOut": false, + "cursorRow": 0, + "cursorCol": 10, + "capturedAtSeq": 1 + } +} diff --git a/dogfood/install-flows/git/install-flow.cast b/dogfood/install-flows/git/install-flow.cast new file mode 100644 index 0000000..e2a7fcd --- /dev/null +++ b/dogfood/install-flows/git/install-flow.cast @@ -0,0 +1,9 @@ +{"version":2,"width":140,"height":40,"timestamp":1775593864,"title":"01KNMT8ERRG69NVF3QF7A0M4PN","sessionId":"01KNMT8ERRG69NVF3QF7A0M4PN","env":{"TERM":"xterm-256color"},"toolVersion":"0.1.0"} +[0,"o","\u001b[?2004h"] +[0.001,"o","bash-5.1$ "] +[3.035,"o","\u001b[7mset -euo pipefail\u001b[27m\r\n\r\u001b[7mprintf '\\033c'\u001b[27m\r\n\r\u001b[7mecho '# git install transcript (blocked in this workspace)'\u001b[27m\r\n\r\u001b[7mtail -n 80 \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/git/install.log\"\u001b[27m\r\n\r\u001b[7mecho '__DOGFOOD_DONE__ install'\u001b[27m\r\n\r\n\r\u001b[7mprintf '%s%s\\n' '__AT_MARKER_8a0684e4735' '94d9ab974f165fb524d89__'\u001b[27m\r\n"] +[3.035,"o","\r\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[Abash-5.1$ set -euo pipefail\r\n\rprintf '\\033c'\r\n\recho '# git install transcript (blocked in this workspace)'\r\n\rtail -n 80 \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/git/install.log\"\r\n\recho '__DOGFOOD_DONE__ install'\r\n\r\n\rprintf '%s%s\\n' '__AT_MARKER_8a0684e4735' '94d9ab974f165fb524d89__'\r\n\r\u001b[A\r\n\u001b[?2004l\r\u001bc# git install transcript (blocked in this workspace)\r\n"] +[3.037,"o","npm error npm error src/renderer/ghosttyWeb/backend.ts(1,28): error TS2307: Cannot find module 'node:crypto' or its corresponding type declarations.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2,31): error TS2307: Cannot find module 'node:module' or its corresponding type declarations.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(8,8): error TS2307: Cannot find module 'node:http' or its corresponding type declarations.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(9,41): error TS2307: Cannot find module 'node:fs/promises' or its corresponding type declarations.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(10,52): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(18,8): error TS2307: Cannot find module 'playwright' or its corresponding type declarations.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(76,9): error TS2580: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(882,19): error TS7006: Parameter 'error' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(903,45): error TS2339: Property 'url' does not exist on type 'ImportMeta'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(921,6): error TS7006: Parameter 'entryName' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(948,11): error TS2580: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(1473,23): error TS2345: Argument of type 'any' is not assignable to parameter of type 'never'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(1610,9): error TS2304: Cannot find name 'setTimeout'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(1731,23): error TS2345: Argument of type 'any' is not assignable to parameter of type 'never'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(1856,27): error TS2580: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2026,54): error TS7006: Parameter 'route' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2081,34): error TS7006: Parameter 'error' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2129,30): error TS2304: Cannot find name 'URLSearchParams'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2205,27): error TS2304: Cannot find name 'URL'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2243,8): error TS7006: Parameter 'opts' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2333,15): error TS7031: Binding element 'nextCols' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2333,25): error TS7031: Binding element 'nextRows' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2380,9): error TS2304: Cannot find name 'setTimeout'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2420,34): error TS7006: Parameter 'request' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2420,43): error TS7006: Parameter 'response' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2462,28): error TS2304: Cannot find name 'URL'.\r\nnpm error npm error src/renderer/ghosttyWeb/backend.ts(2522,32): error TS7006: Parameter 'nextData' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/profiles.ts(1,28): error TS2307: Cannot find module 'node:crypto' or its corresponding type declarations.\r\nnpm error npm error src/renderer/profiles.ts(3,31): error TS2307: Cannot find module 'zod' or its corresponding type declarations.\r\nnpm error npm error src/renderer/profiles.ts(89,11): error TS7006: Parameter 'issue' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/profiles.ts(200,31): error TS7006: Parameter 'fontAsset' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/types.ts(1,19): error TS2307: Cannot find module 'zod' or its corresponding type declarations.\r\nnpm error npm error src/renderer/types.ts(29,12): error TS7006: Parameter 'value' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/types.ts(170,19): error TS7031: Binding element 'events' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/types.ts(170,29): error TS7006: Parameter 'context' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/types.ts(275,19): error TS7031: Binding element 'fontAssets' implicitly has an 'any' type.\r\nnpm error npm error src/renderer/types.ts(275,33): error TS7006: Parameter 'context' implicitly has an 'any' type.\r\nnpm error npm error src/replay/offlineReplay.ts(1,47): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\n"] +[3.037,"o","npm error npm error src/storage/artifactHealth.ts(1,24): error TS2307: Cannot find module 'node:fs/promises' or its corresponding type declarations.\r\nnpm error npm error src/storage/artifactHealth.ts(2,37): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/storage/artifactHealth.ts(78,37): error TS7006: Parameter 'artifact' implicitly has an 'any' type.\r\nnpm error npm error src/storage/artifactHealth.ts(95,6): error TS7006: Parameter 'artifact' implicitly has an 'any' type.\r\nnpm error npm error src/storage/artifactManifest.ts(1,35): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/storage/artifactManifest.ts(3,22): error TS2307: Cannot find module 'ulid' or its corresponding type declarations.\r\nnpm error npm error src/storage/artifactManifest.ts(4,19): error TS2307: Cannot find module 'zod' or its corresponding type declarations.\r\nnpm error npm error src/storage/artifactManifest.ts(27,8): error TS7006: Parameter 'value' implicitly has an 'any' type.\r\nnpm error npm error src/storage/artifactPaths.ts(1,23): error TS2307: Cannot find module 'node:fs/promises' or its corresponding type declarations.\r\nnpm error npm error src/storage/artifactPaths.ts(2,46): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/storage/home.ts(1,30): error TS2307: Cannot find module 'node:fs' or its corresponding type declarations.\r\nnpm error npm error src/storage/home.ts(2,23): error TS2307: Cannot find module 'node:fs/promises' or its corresponding type declarations.\r\nnpm error npm error src/storage/home.ts(3,25): error TS2307: Cannot find module 'node:os' or its corresponding type declarations.\r\nnpm error npm error src/storage/home.ts(4,45): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/storage/home.ts(5,21): error TS2307: Cannot find module 'node:process' or its corresponding type declarations.\r\nnpm error npm error src/storage/manifests.ts(1,28): error TS2307: Cannot find module 'node:crypto' or its corresponding type declarations.\r\nnpm error npm error src/storage/manifests.ts(2,56): error TS2307: Cannot find module 'node:fs/promises' or its corresponding type declarations.\r\nnpm error npm error src/storage/manifests.ts(3,37): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/storage/sessionPaths.ts(1,46): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/tools/review-bundle.ts(9,8): error TS2307: Cannot find module 'node:fs/promises' or its corresponding type declarations.\r\nnpm error npm error src/tools/review-bundle.ts(18,8): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/tools/review-bundle.ts(19,21): error TS2307: Cannot find module 'node:process' or its corresponding type declarations.\r\nnpm error npm error src/tools/review-bundle.ts(20,31): error TS2307: Cannot find module 'node:url' or its corresponding type declarations.\r\nnpm error npm error src/tools/review-bundle.ts(22,19): error TS2307: Cannot find module 'zod' or its corresponding type declarations.\r\nnpm error npm error src/tools/review-bundle.ts(504,17): error TS7006: Parameter 'left' implicitly has an 'any' type.\r\nnpm error npm error src/tools/review-bundle.ts(504,23): error TS7006: Parameter 'right' implicitly has an 'any' type.\r\nnpm error npm error src/tools/review-bundle.ts(1275,16): error TS7006: Parameter 'entry' implicitly has an 'any' type.\r\nnpm error npm error src/tools/review-bundle.ts(1276,13): error TS7006: Parameter 'entry' implicitly has an 'any' type.\r\nnpm error npm error src/tools/review-bundle.ts(1277,14): error TS7006: Parameter 'left' implicitly has an 'any' type.\r\nnpm error npm error src/tools/review-bundle.ts(1277,20): error TS7006: Parameter 'right' implicitly has an 'any' type.\r\nnpm error npm error src/tools/review-bundle.ts(1328,22): error"] +[3.038,"o"," TS2339: Property 'url' does not exist on type 'ImportMeta'.\r\nnpm error npm error src/tools/validate-bundle.ts(7,42): error TS2307: Cannot find module 'node:fs/promises' or its corresponding type declarations.\r\nnpm error npm error src/tools/validate-bundle.ts(8,31): error TS2307: Cannot find module 'node:path' or its corresponding type declarations.\r\nnpm error npm error src/tools/validate-bundle.ts(9,21): error TS2307: Cannot find module 'node:process' or its corresponding type declarations.\r\nnpm error npm error src/tools/validate-bundle.ts(10,31): error TS2307: Cannot find module 'node:url' or its corresponding type declarations.\r\nnpm error npm error src/tools/validate-bundle.ts(362,22): error TS2339: Property 'url' does not exist on type 'ImportMeta'.\r\nnpm error npm error src/util/assert.ts(1,20): error TS2307: Cannot find module 'node:assert/strict' or its corresponding type declarations.\r\nnpm error npm error src/util/logger.ts(1,21): error TS2307: Cannot find module 'node:process' or its corresponding type declarations.\r\nnpm error npm error src/util/logger.ts(138,8): error TS2503: Cannot find namespace 'NodeJS'.\r\nnpm error npm error npm warn using --force Recommended protections disabled.\r\nnpm error npm error A complete log of this run can be found in: /home/coder/.npm/_logs/2026-04-07T20_24_51_518Z-debug-0.log\r\nnpm error A complete log of this run can be found in: /home/coder/.npm/_logs/2026-04-07T20_24_44_176Z-debug-0.log\r\n"] +[3.038,"o","__DOGFOOD_DONE__ install\r\n__AT_MARKER_8a0684e473594d9ab974f165fb524d89__\r\n\u001b[?2004hbash-5.1$ "] diff --git a/dogfood/install-flows/git/install-flow.webm b/dogfood/install-flows/git/install-flow.webm new file mode 100644 index 0000000..3c86650 Binary files /dev/null and b/dogfood/install-flows/git/install-flow.webm differ diff --git a/dogfood/install-flows/git/install-prefix.txt b/dogfood/install-flows/git/install-prefix.txt new file mode 100644 index 0000000..34c4754 --- /dev/null +++ b/dogfood/install-flows/git/install-prefix.txt @@ -0,0 +1 @@ +/tmp/tmp.Yb9QnNF597 diff --git a/dogfood/install-flows/git/install-run.json b/dogfood/install-flows/git/install-run.json new file mode 100644 index 0000000..cdd7518 --- /dev/null +++ b/dogfood/install-flows/git/install-run.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "run", + "timestamp": "2026-04-07T20:31:08.184Z", + "result": { + "accepted": true, + "completed": true, + "timedOut": false, + "seq": 2, + "durationMs": 402, + "marker": "__AT_MARKER_8a0684e473594d9ab974f165fb524d89__" + } +} diff --git a/dogfood/install-flows/git/install-screenshot.json b/dogfood/install-flows/git/install-screenshot.json new file mode 100644 index 0000000..f28c619 --- /dev/null +++ b/dogfood/install-flows/git/install-screenshot.json @@ -0,0 +1,20 @@ +{ + "ok": true, + "command": "screenshot", + "timestamp": "2026-04-07T20:31:10.121Z", + "result": { + "sessionId": "01KNMT8ERRG69NVF3QF7A0M4PN", + "capturedAtSeq": 8, + "profileName": "reference-dark", + "cols": 140, + "rows": 40, + "artifactPath": "/tmp/tmp.vQk7Eo2uSg/sessions/01KNMT8ERRG69NVF3QF7A0M4PN/artifacts/screenshot-8-reference-dark.png", + "pngSizeBytes": 200443, + "cursorVisible": false, + "rendererBackend": "ghostty-web", + "pixelWidth": 1120, + "pixelHeight": 640, + "sha256": "6f1a73de5eb8437ca2c27a506650dba81c3f039c5a253cc52f160391ae87d8d6", + "renderProfileHash": "8ffed6af301ec7c0e6b69599c3be0d1d12096f9fcdfc59d0bbb4cc474d64c53d" + } +} diff --git a/dogfood/install-flows/git/install-step.sh b/dogfood/install-flows/git/install-step.sh new file mode 100644 index 0000000..2006f43 --- /dev/null +++ b/dogfood/install-flows/git/install-step.sh @@ -0,0 +1,5 @@ +set -euo pipefail +printf '\033c' +echo '# git install transcript (blocked in this workspace)' +tail -n 80 "/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/git/install.log" +echo '__DOGFOOD_DONE__ install' diff --git a/dogfood/install-flows/git/install-wait.json b/dogfood/install-flows/git/install-wait.json new file mode 100644 index 0000000..ac57ad1 --- /dev/null +++ b/dogfood/install-flows/git/install-wait.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "wait", + "timestamp": "2026-04-07T20:31:09.162Z", + "result": { + "matched": true, + "timedOut": false, + "matchedText": "__DOGFOOD_DONE__ install", + "cursorRow": 39, + "cursorCol": 10, + "capturedAtSeq": 8 + } +} diff --git a/dogfood/install-flows/git/install.png b/dogfood/install-flows/git/install.png new file mode 100644 index 0000000..319f8ba Binary files /dev/null and b/dogfood/install-flows/git/install.png differ diff --git a/dogfood/install-flows/git/installed-home.txt b/dogfood/install-flows/git/installed-home.txt new file mode 100644 index 0000000..56dbf65 --- /dev/null +++ b/dogfood/install-flows/git/installed-home.txt @@ -0,0 +1 @@ +/tmp/tmp.nGHJwt9r49 diff --git a/dogfood/install-flows/git/record-asciicast.json b/dogfood/install-flows/git/record-asciicast.json new file mode 100644 index 0000000..26a90c7 --- /dev/null +++ b/dogfood/install-flows/git/record-asciicast.json @@ -0,0 +1,23 @@ +{ + "ok": true, + "command": "record export", + "timestamp": "2026-04-07T20:31:13.911Z", + "result": { + "sessionId": "01KNMT8ERRG69NVF3QF7A0M4PN", + "format": "asciicast", + "artifactPath": "/tmp/tmp.vQk7Eo2uSg/sessions/01KNMT8ERRG69NVF3QF7A0M4PN/artifacts/recording-8-asciicast.cast", + "bytes": 12208, + "sha256": "5c5256639d3ccc05815f3f0da671b9baf320110ba0e3de94ff803417b34f21fe", + "capturedAtSeq": 8, + "durationMs": 3038, + "metadata": { + "width": 140, + "height": 40, + "title": "01KNMT8ERRG69NVF3QF7A0M4PN", + "timestamp": 1775593864, + "outputEventCount": 8, + "resizeEventCount": 0, + "markerCount": 0 + } + } +} diff --git a/dogfood/install-flows/git/record-webm.json b/dogfood/install-flows/git/record-webm.json new file mode 100644 index 0000000..7dc572a --- /dev/null +++ b/dogfood/install-flows/git/record-webm.json @@ -0,0 +1,23 @@ +{ + "ok": true, + "command": "record export", + "timestamp": "2026-04-07T20:31:13.104Z", + "result": { + "sessionId": "01KNMT8ERRG69NVF3QF7A0M4PN", + "format": "webm", + "artifactPath": "/tmp/tmp.vQk7Eo2uSg/sessions/01KNMT8ERRG69NVF3QF7A0M4PN/artifacts/recording-8-webm.webm", + "bytes": 438307, + "sha256": "6c3075f3066643e2893f5f14df2023ce04ce1ed3042c47283854056c375b72f6", + "capturedAtSeq": 8, + "durationMs": 3038, + "metadata": { + "width": 140, + "height": 40, + "profileName": "reference-dark", + "renderProfileHash": "8ffed6af301ec7c0e6b69599c3be0d1d12096f9fcdfc59d0bbb4cc474d64c53d", + "timingMode": "accelerated", + "outputEventCount": 8, + "resizeEventCount": 0 + } + } +} diff --git a/dogfood/install-flows/git/session-id.txt b/dogfood/install-flows/git/session-id.txt new file mode 100644 index 0000000..34db3c1 --- /dev/null +++ b/dogfood/install-flows/git/session-id.txt @@ -0,0 +1 @@ +01KNMT8ERRG69NVF3QF7A0M4PN diff --git a/dogfood/install-flows/tarball-artifact/agent-terminal-0.1.0.tgz b/dogfood/install-flows/tarball-artifact/agent-terminal-0.1.0.tgz new file mode 100644 index 0000000..75f4d2b Binary files /dev/null and b/dogfood/install-flows/tarball-artifact/agent-terminal-0.1.0.tgz differ diff --git a/dogfood/install-flows/tarball/agent-terminal-home.txt b/dogfood/install-flows/tarball/agent-terminal-home.txt new file mode 100644 index 0000000..04f8522 --- /dev/null +++ b/dogfood/install-flows/tarball/agent-terminal-home.txt @@ -0,0 +1 @@ +/tmp/tmp.0v4LnZJ3BC diff --git a/dogfood/install-flows/tarball/create.json b/dogfood/install-flows/tarball/create.json new file mode 100644 index 0000000..8d39407 --- /dev/null +++ b/dogfood/install-flows/tarball/create.json @@ -0,0 +1,12 @@ +{ + "ok": true, + "command": "create", + "timestamp": "2026-04-07T20:30:17.970Z", + "result": { + "sessionId": "01KNMT70YKGVN6PR3MWWAK7MMM", + "createdAt": "2026-04-07T20:30:17.045Z", + "cols": 140, + "rows": 40, + "shell": "/bin/bash" + } +} diff --git a/dogfood/install-flows/tarball/destroy.json b/dogfood/install-flows/tarball/destroy.json new file mode 100644 index 0000000..ab8aae6 --- /dev/null +++ b/dogfood/install-flows/tarball/destroy.json @@ -0,0 +1,9 @@ +{ + "ok": true, + "command": "destroy", + "timestamp": "2026-04-07T20:30:34.477Z", + "result": { + "sessionId": "01KNMT70YKGVN6PR3MWWAK7MMM", + "destroyed": true + } +} diff --git a/dogfood/install-flows/tarball/doctor-run.json b/dogfood/install-flows/tarball/doctor-run.json new file mode 100644 index 0000000..2882329 --- /dev/null +++ b/dogfood/install-flows/tarball/doctor-run.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "run", + "timestamp": "2026-04-07T20:30:27.586Z", + "result": { + "accepted": true, + "completed": true, + "timedOut": false, + "seq": 14, + "durationMs": 373, + "marker": "__AT_MARKER_38b566000a9c4c23814ed1890c2ff130__" + } +} diff --git a/dogfood/install-flows/tarball/doctor-screenshot.json b/dogfood/install-flows/tarball/doctor-screenshot.json new file mode 100644 index 0000000..287364c --- /dev/null +++ b/dogfood/install-flows/tarball/doctor-screenshot.json @@ -0,0 +1,20 @@ +{ + "ok": true, + "command": "screenshot", + "timestamp": "2026-04-07T20:30:29.514Z", + "result": { + "sessionId": "01KNMT70YKGVN6PR3MWWAK7MMM", + "capturedAtSeq": 22, + "profileName": "reference-dark", + "cols": 140, + "rows": 40, + "artifactPath": "/tmp/tmp.0v4LnZJ3BC/sessions/01KNMT70YKGVN6PR3MWWAK7MMM/artifacts/screenshot-22-reference-dark.png", + "pngSizeBytes": 68200, + "cursorVisible": false, + "rendererBackend": "ghostty-web", + "pixelWidth": 1120, + "pixelHeight": 640, + "sha256": "b70bee6766e56a840b882b8bb8ac46ed629b13eb1ae445ba0a62563ab560e134", + "renderProfileHash": "8ffed6af301ec7c0e6b69599c3be0d1d12096f9fcdfc59d0bbb4cc474d64c53d" + } +} diff --git a/dogfood/install-flows/tarball/doctor-step.sh b/dogfood/install-flows/tarball/doctor-step.sh new file mode 100644 index 0000000..565008b --- /dev/null +++ b/dogfood/install-flows/tarball/doctor-step.sh @@ -0,0 +1,5 @@ +set -euo pipefail +printf '\033c' +echo '# tarball doctor' +cat "/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/doctor.json" +echo '__DOGFOOD_DONE__ doctor' diff --git a/dogfood/install-flows/tarball/doctor-wait.json b/dogfood/install-flows/tarball/doctor-wait.json new file mode 100644 index 0000000..fe80bc8 --- /dev/null +++ b/dogfood/install-flows/tarball/doctor-wait.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "wait", + "timestamp": "2026-04-07T20:30:28.623Z", + "result": { + "matched": true, + "timedOut": false, + "matchedText": "__DOGFOOD_DONE__ doctor", + "cursorRow": 39, + "cursorCol": 10, + "capturedAtSeq": 22 + } +} diff --git a/dogfood/install-flows/tarball/doctor.json b/dogfood/install-flows/tarball/doctor.json new file mode 100644 index 0000000..b4162b5 --- /dev/null +++ b/dogfood/install-flows/tarball/doctor.json @@ -0,0 +1,130 @@ +{ + "ok": true, + "command": "doctor", + "timestamp": "2026-04-07T20:24:42.407Z", + "result": { + "ok": true, + "checks": { + "environment": [ + { + "name": "node-runtime", + "status": "pass", + "message": "Node 24.14.0 ok", + "durationMs": 0 + }, + { + "name": "cwd-access", + "status": "pass", + "message": "cwd read/write: /home/coder/.mux/src/agent-terminal/npm-install-5r2j", + "durationMs": 0 + }, + { + "name": "temp-dir", + "status": "pass", + "message": "temp dir ok: /tmp", + "durationMs": 1 + }, + { + "name": "home_isolation", + "status": "pass", + "message": "Agent-terminal home is isolated from system home: /tmp/tmp.fEPNel7eC1", + "durationMs": 0 + }, + { + "name": "home-writable", + "status": "pass", + "message": "home writable: /tmp/tmp.fEPNel7eC1", + "durationMs": 2 + }, + { + "name": "pty-spawn", + "status": "pass", + "message": "spawned /home/coder/.npm/_npx/387698761821791d/node_modules/node/bin/node", + "durationMs": 35 + }, + { + "name": "socket-viable", + "status": "pass", + "message": "socket ok: /tmp/tmp.fEPNel7eC1/sessions/doctor-3625363-mnp2ij52-2/host.sock", + "durationMs": 3 + }, + { + "name": "artifact-atomicity", + "status": "pass", + "message": "atomic rename ok: /tmp/tmp.fEPNel7eC1/sessions/doctor-3625363-mnp2ij55-3/artifacts", + "durationMs": 2 + }, + { + "name": "event-log-writable", + "status": "pass", + "message": "append ok: /tmp/tmp.fEPNel7eC1/sessions/doctor-3625363-mnp2ij57-5/events.jsonl", + "durationMs": 1 + } + ], + "renderer": [ + { + "name": "playwright_available", + "status": "pass", + "message": "available", + "durationMs": 0 + }, + { + "name": "browser_cache_accessible", + "status": "pass", + "message": "browser cache accessible: /home/coder/.cache/ms-playwright", + "durationMs": 0 + }, + { + "name": "browser_launch", + "status": "pass", + "message": "chromium launches", + "durationMs": 144 + }, + { + "name": "ghostty_web_available", + "status": "pass", + "message": "WASM available", + "durationMs": 10 + }, + { + "name": "screenshot_viable", + "status": "pass", + "message": "viable", + "durationMs": 159 + } + ] + }, + "capabilities": [ + { + "name": "snapshot", + "status": "available", + "reason": "built-in capability", + "detail": "available without external renderer dependencies" + }, + { + "name": "wait", + "status": "available", + "reason": "built-in capability", + "detail": "available without external renderer dependencies" + }, + { + "name": "screenshot", + "status": "available", + "reason": "renderer smoke checks passed", + "detail": "playwright_available: available; browser_launch: chromium launches; ghostty_web_available: WASM available; screenshot_viable: viable" + }, + { + "name": "record-export-asciicast", + "status": "available", + "reason": "built-in capability", + "detail": "available without external renderer dependencies" + }, + { + "name": "record-export-webm", + "status": "available", + "reason": "browser-backed export dependencies available", + "detail": "playwright_available: available; browser_launch: chromium launches; ghostty_web_available: WASM available" + } + ] + } +} diff --git a/dogfood/install-flows/tarball/doctor.png b/dogfood/install-flows/tarball/doctor.png new file mode 100644 index 0000000..b94bd02 Binary files /dev/null and b/dogfood/install-flows/tarball/doctor.png differ diff --git a/dogfood/install-flows/tarball/initial-wait.json b/dogfood/install-flows/tarball/initial-wait.json new file mode 100644 index 0000000..b44eaee --- /dev/null +++ b/dogfood/install-flows/tarball/initial-wait.json @@ -0,0 +1,12 @@ +{ + "ok": true, + "command": "wait", + "timestamp": "2026-04-07T20:30:20.227Z", + "result": { + "matched": true, + "timedOut": false, + "cursorRow": 0, + "cursorCol": 10, + "capturedAtSeq": 1 + } +} diff --git a/dogfood/install-flows/tarball/install-flow.cast b/dogfood/install-flows/tarball/install-flow.cast new file mode 100644 index 0000000..48bb56a --- /dev/null +++ b/dogfood/install-flows/tarball/install-flow.cast @@ -0,0 +1,21 @@ +{"version":2,"width":140,"height":40,"timestamp":1775593817,"title":"01KNMT70YKGVN6PR3MWWAK7MMM","sessionId":"01KNMT70YKGVN6PR3MWWAK7MMM","env":{"TERM":"xterm-256color"},"toolVersion":"0.1.0"} +[0,"o","\u001b[?2004h"] +[0.001,"o","bash-5.1$ "] +[3.102,"o","\u001b[7mset -euo pipefail\u001b[27m\r\n\r\u001b[7mprintf '\\033c'\u001b[27m\r\n\r\u001b[7mecho '# tarball install transcript'\u001b[27m\r\n\r\u001b[7mtail -n 60 \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/install.log\"\u001b[27m\r\n\r\u001b[7mecho '__DOGFOOD_DONE__ install'\u001b[27m\r\n\r\n\r\u001b[7mprintf '%s%s\\n' '__AT_MARKER_a451c1cc155' '44616bb8029b5478a0646__'\u001b[27m\r\n\r\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[Abash-5.1$ set -euo pipefail\r\n\rprintf '\\033c'\r\n\recho '# tarball install transcript'\r\n\rtail -n 60 \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/install.log\"\r\n\recho '__DOGFOOD_DONE__ install'\r\n\r\n\rprintf '%s%s\\n' '__AT_MARKER_a451c1cc155' '44616bb8029b5478a0646__'\r\n\r\u001b[A\r\n\u001b[?2004l\r"] +[3.102,"o","\u001bc# tarball install transcript\r\n"] +[3.104,"o","\r\nadded 9 packages in 3s\r\n\r\n1 package is looking for funding\r\n run `npm fund` for details\r\n"] +[3.104,"o","__DOGFOOD_DONE__ install\r\n"] +[3.104,"o","__AT_MARKER_a451c1cc15544616bb8029b5478a0646__\r\n\u001b[?2004hbash-5.1$ "] +[6.249,"o","\u001b[7mset -euo pipefail\u001b[27m\r\n\r\u001b[7mprintf '\\033c'\u001b[27m\r\n\r\u001b[7mecho '# tarball version'\u001b[27m\r\n\r\u001b[7mcat \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/version.json\"\u001b[27m\r\n"] +[6.249,"o","\r\u001b[7mecho '__DOGFOOD_DONE__ version'\u001b[27m\r\n\r\n\r\u001b[7mprintf '%s%s\\n' '__AT_MARKER_2c25feae98d' '4433fb02d6dedda1398a8__'\u001b[27m\r\n\r\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[Abash-5.1$ set -euo pipefail\r\n\rprintf '\\033c'\r\n\recho '# tarball version'\r\n\rcat \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/version.json\"\r\n\recho '__DOGFOOD_DONE__ version'\r\n\r\n\rprintf '%s%s\\n' '__AT_MARKER_2c25feae98d' '4433fb02d6dedda1398a8__'\r\n\r\u001b[A\r\n\u001b[?2004l\r\u001bc# tarball version\r\n"] +[6.251,"o","{\r\n \"ok\": true,\r\n \"command\": \"version\",\r\n \"timestamp\": \"2026-04-07T20:24:41.640Z\",\r\n \"result\": {\r\n \"cliVersion\": \"0.1.0\",\r\n \"protocolVersion\": \"0.1.0\",\r\n \"rendererBackends\": [\r\n \"ghostty-web\"\r\n ],\r\n \"runtime\": {\r\n \"node\": \"v24.14.0\",\r\n \"platform\": \"linux\",\r\n \"arch\": \"x64\"\r\n },\r\n \"capabilities\": [\r\n {\r\n \"name\": \"snapshot\",\r\n \"status\": \"available\"\r\n },\r\n {\r\n \"name\": \"wait\",\r\n \"status\": \"available\"\r\n },\r\n {\r\n \"name\": \"screenshot\",\r\n \"status\": \"available\"\r\n },\r\n {\r\n \"name\": \"record-export-asciicast\",\r\n \"status\": \"available\"\r\n },\r\n {\r\n \"name\": \"record-export-webm\",\r\n \"status\": \"available\"\r\n }\r\n ]\r\n }\r\n}\r\n"] +[6.251,"o","__DOGFOOD_DONE__ version\r\n"] +[6.251,"o","__AT_MARKER_2c25feae98d4433fb02d6dedda1398a8__\r\n\u001b[?2004hbash-5.1$ "] +[9.345,"o","\u001b[7mset -euo pipefail\u001b[27m\r\n\r\u001b[7mprintf '\\033c'\u001b[27m\r\n\r\u001b[7mecho '# tarball doctor'\u001b[27m\r\n\r\u001b[7mcat \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/doctor.json\"\u001b[27m\r\n\r\u001b[7mecho '__DOGFOOD_DONE__ doctor'\u001b[27m\r\n\r\n"] +[9.345,"o","\r\u001b[7mprintf '%s%s\\n' '__AT_MARKER_38b566000a9' 'c4c23814ed1890c2ff130__'\u001b[27m\r\n\r\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[A\u001b[Abash-5.1$ set -euo pipefail\r\n\rprintf '\\033c'\r\n\recho '# tarball doctor'\r\n\rcat \"/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/doctor.json\"\r\n\recho '__DOGFOOD_DONE__ doctor'\r\n\r\n\rprintf '%s%s\\n' '__AT_MARKER_38b566000a9' 'c4c23814ed1890c2ff130__'\r\n\r\u001b[A\r\n\u001b[?2004l\r"] +[9.345,"o","\u001bc# tarball doctor\r\n"] +[9.347,"o","{\r\n \"ok\": true,\r\n \"command\": \"doctor\",\r\n \"timestamp\": \"2026-04-07T20:24:42.407Z\",\r\n \"result\": {\r\n \"ok\": true,\r\n \"checks\": {\r\n \"environment\": [\r\n {\r\n \"name\": \"node-runtime\",\r\n \"status\": \"pass\",\r\n \"message\": \"Node 24.14.0 ok\",\r\n \"durationMs\": 0\r\n },\r\n {\r\n \"name\": \"cwd-access\",\r\n \"status\": \"pass\",\r\n \"message\": \"cwd read/write: /home/coder/.mux/src/agent-terminal/npm-install-5r2j\",\r\n \"durationMs\": 0\r\n },\r\n {\r\n \"name\": \"temp-dir\",\r\n \"status\": \"pass\",\r\n \"message\": \"temp dir ok: /tmp\",\r\n \"durationMs\": 1\r\n },\r\n {\r\n \"name\": \"home_isolation\",\r\n \"status\": \"pass\",\r\n \"message\": \"Agent-terminal home is isolated from system home: /tmp/tmp.fEPNel7eC1\",\r\n \"durationMs\": 0\r\n },\r\n"] +[9.347,"o"," {\r\n \"name\": \"home-writable\",\r\n \"status\": \"pass\",\r\n \"message\": \"home writable: /tmp/tmp.fEPNel7eC1\",\r\n \"durationMs\": 2\r\n },\r\n {\r\n \"name\": \"pty-spawn\",\r\n \"status\": \"pass\",\r\n \"message\": \"spawned /home/coder/.npm/_npx/387698761821791d/node_modules/node/bin/node\",\r\n \"durationMs\": 35\r\n },\r\n {\r\n \"name\": \"socket-viable\",\r\n \"status\": \"pass\",\r\n \"message\": \"socket ok: /tmp/tmp.fEPNel7eC1/sessions/doctor-3625363-mnp2ij52-2/host.sock\",\r\n \"durationMs\": 3\r\n },\r\n {\r\n \"name\": \"artifact-atomicity\",\r\n \"status\": \"pass\",\r\n \"message\": \"atomic rename ok: /tmp/tmp.fEPNel7eC1/sessions/doctor-3625363-mnp2ij55-3/artifacts\",\r\n \"durationMs\": 2\r\n },\r\n {\r\n \"name\": \"event-log-writable\",\r\n \"status\": \"pass\",\r\n \"message\": \"append ok: /tmp/tmp.fEPNel7eC1/sessions/doctor-3625363-mnp2ij57-5/events.jsonl\",\r\n \"durationMs\": 1\r\n }\r\n ],\r\n \"renderer\": [\r\n {\r\n \"name\": \"playwright_available\",\r\n \"status\": \"pass\",\r\n \"message\": \"available\",\r\n \"durationMs\": 0\r\n },\r\n {\r\n \"name\": \"browser_cache_accessible\",\r\n \"status\": \"pass\",\r\n \"message\": \"browser cache accessible: /home/coder/.cache/ms-playwright\",\r\n \"durationMs\": 0\r\n },\r\n {\r\n \"name\": \"browser_launch\",\r\n \"status\": \"pass\",\r\n \"message\": \"chromium launches\",\r\n \"durationMs\": 144\r\n },\r\n {\r\n \"name\": \"ghostty_web_available\",\r\n \"status\": \"pass\",\r\n \"message\": \"WASM available\",\r\n \"durationMs\": 10\r\n },\r\n {\r\n \"name\": \"screenshot_viable\",\r\n \"status\": \"pass\",\r\n \"message\": \"viable\",\r\n \"durationMs\": 159\r\n }\r\n ]\r\n },\r\n \"capabilities\": [\r\n {\r\n \"name\": \"snapshot\",\r\n \"status\": \"available\",\r\n \"reason\": \"built-in capability\",\r\n \"detail\": \"available without external renderer dependencies\"\r\n },\r\n {\r\n \"name\": \"wait\",\r\n \"status\": \"available\",\r\n \"reason\": \"built-in capability\",\r\n \"detail\": \"available without external renderer dependencies\"\r\n },\r\n {\r\n \"name\": \"screenshot\",\r\n \"status\": \"available\",\r\n \"reason\": \"renderer smoke checks passed\",\r\n \"detail\": \"playwright_available: available; browser_launch: chromium launches; ghostty_web_available: WASM available; screenshot_viable: viable\"\r\n },\r\n {\r\n \"name\": \"record-export-asciicast\",\r\n \"status\": \"available\",\r\n \"reason\": \"built-in capability\",\r\n \"detail\": \"available without external renderer dependencies\"\r\n },\r\n {\r\n \"name\": \"record-export-webm\",\r\n \"status\": \"available\",\r\n \"reason\": \"browser-backed export dependencies available\",\r\n \"detail\": \"playwright_available: available; browser_launch: chromium launches; ghostty_web_available: WASM available\"\r\n }\r\n ]\r\n }\r\n}\r\n"] +[9.347,"o","__DOGFOOD_DONE__ doctor\r\n"] +[9.347,"o","__AT_MARKER_38b566000a9c4c23814ed1890c2ff130__\r\n\u001b[?2004h"] +[9.348,"o","bash-5.1$ "] diff --git a/dogfood/install-flows/tarball/install-flow.webm b/dogfood/install-flows/tarball/install-flow.webm new file mode 100644 index 0000000..a764d80 Binary files /dev/null and b/dogfood/install-flows/tarball/install-flow.webm differ diff --git a/dogfood/install-flows/tarball/install-prefix.txt b/dogfood/install-flows/tarball/install-prefix.txt new file mode 100644 index 0000000..818054a --- /dev/null +++ b/dogfood/install-flows/tarball/install-prefix.txt @@ -0,0 +1 @@ +/tmp/tmp.hbKzZn18R2 diff --git a/dogfood/install-flows/tarball/install-run.json b/dogfood/install-flows/tarball/install-run.json new file mode 100644 index 0000000..13a8a39 --- /dev/null +++ b/dogfood/install-flows/tarball/install-run.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "run", + "timestamp": "2026-04-07T20:30:21.279Z", + "result": { + "accepted": true, + "completed": true, + "timedOut": false, + "seq": 2, + "durationMs": 307, + "marker": "__AT_MARKER_a451c1cc15544616bb8029b5478a0646__" + } +} diff --git a/dogfood/install-flows/tarball/install-screenshot.json b/dogfood/install-flows/tarball/install-screenshot.json new file mode 100644 index 0000000..09603e4 --- /dev/null +++ b/dogfood/install-flows/tarball/install-screenshot.json @@ -0,0 +1,20 @@ +{ + "ok": true, + "command": "screenshot", + "timestamp": "2026-04-07T20:30:23.338Z", + "result": { + "sessionId": "01KNMT70YKGVN6PR3MWWAK7MMM", + "capturedAtSeq": 7, + "profileName": "reference-dark", + "cols": 140, + "rows": 40, + "artifactPath": "/tmp/tmp.0v4LnZJ3BC/sessions/01KNMT70YKGVN6PR3MWWAK7MMM/artifacts/screenshot-7-reference-dark.png", + "pngSizeBytes": 19750, + "cursorVisible": false, + "rendererBackend": "ghostty-web", + "pixelWidth": 1120, + "pixelHeight": 640, + "sha256": "54304dec97108f354be09b1c8577589c74c7233ddcc48aea983646097c8caaf4", + "renderProfileHash": "8ffed6af301ec7c0e6b69599c3be0d1d12096f9fcdfc59d0bbb4cc474d64c53d" + } +} diff --git a/dogfood/install-flows/tarball/install-step.sh b/dogfood/install-flows/tarball/install-step.sh new file mode 100644 index 0000000..40e1157 --- /dev/null +++ b/dogfood/install-flows/tarball/install-step.sh @@ -0,0 +1,5 @@ +set -euo pipefail +printf '\033c' +echo '# tarball install transcript' +tail -n 60 "/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/install.log" +echo '__DOGFOOD_DONE__ install' diff --git a/dogfood/install-flows/tarball/install-wait.json b/dogfood/install-flows/tarball/install-wait.json new file mode 100644 index 0000000..e292c28 --- /dev/null +++ b/dogfood/install-flows/tarball/install-wait.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "wait", + "timestamp": "2026-04-07T20:30:22.273Z", + "result": { + "matched": true, + "timedOut": false, + "matchedText": "__DOGFOOD_DONE__ install", + "cursorRow": 8, + "cursorCol": 10, + "capturedAtSeq": 7 + } +} diff --git a/dogfood/install-flows/tarball/install.png b/dogfood/install-flows/tarball/install.png new file mode 100644 index 0000000..1070c57 Binary files /dev/null and b/dogfood/install-flows/tarball/install.png differ diff --git a/dogfood/install-flows/tarball/installed-home.txt b/dogfood/install-flows/tarball/installed-home.txt new file mode 100644 index 0000000..7763f2b --- /dev/null +++ b/dogfood/install-flows/tarball/installed-home.txt @@ -0,0 +1 @@ +/tmp/tmp.fEPNel7eC1 diff --git a/dogfood/install-flows/tarball/pack.json b/dogfood/install-flows/tarball/pack.json new file mode 100644 index 0000000..b83b055 --- /dev/null +++ b/dogfood/install-flows/tarball/pack.json @@ -0,0 +1,1366 @@ +[ + { + "id": "agent-terminal@0.1.0", + "name": "agent-terminal", + "version": "0.1.0", + "size": 1770156, + "unpackedSize": 3527634, + "shasum": "3cc2c705232965a1ac6d7d937221cdc86a13486c", + "integrity": "sha512-YH+dm8Lz6xw2ifNWr1D4fH6cKNIM2nfVFFPEZDe7MkcMOBMNwYngfgAkT9UFncrEs8KtLjklvNdkK41zxneS6w==", + "filename": "agent-terminal-0.1.0.tgz", + "files": [ + { + "path": "README.md", + "size": 12604, + "mode": 384 + }, + { + "path": "dist/cli/commands/create.d.ts", + "size": 646, + "mode": 384 + }, + { + "path": "dist/cli/commands/create.d.ts.map", + "size": 804, + "mode": 384 + }, + { + "path": "dist/cli/commands/create.js", + "size": 6337, + "mode": 384 + }, + { + "path": "dist/cli/commands/create.js.map", + "size": 5514, + "mode": 384 + }, + { + "path": "dist/cli/commands/destroy.d.ts", + "size": 222, + "mode": 384 + }, + { + "path": "dist/cli/commands/destroy.d.ts.map", + "size": 295, + "mode": 384 + }, + { + "path": "dist/cli/commands/destroy.js", + "size": 499, + "mode": 384 + }, + { + "path": "dist/cli/commands/destroy.js.map", + "size": 558, + "mode": 384 + }, + { + "path": "dist/cli/commands/doctor.d.ts", + "size": 2864, + "mode": 384 + }, + { + "path": "dist/cli/commands/doctor.d.ts.map", + "size": 2606, + "mode": 384 + }, + { + "path": "dist/cli/commands/doctor.js", + "size": 21496, + "mode": 384 + }, + { + "path": "dist/cli/commands/doctor.js.map", + "size": 19752, + "mode": 384 + }, + { + "path": "dist/cli/commands/gc.d.ts", + "size": 1370, + "mode": 384 + }, + { + "path": "dist/cli/commands/gc.d.ts.map", + "size": 1464, + "mode": 384 + }, + { + "path": "dist/cli/commands/gc.js", + "size": 11141, + "mode": 384 + }, + { + "path": "dist/cli/commands/gc.js.map", + "size": 9620, + "mode": 384 + }, + { + "path": "dist/cli/commands/inputSource.d.ts", + "size": 360, + "mode": 384 + }, + { + "path": "dist/cli/commands/inputSource.d.ts.map", + "size": 384, + "mode": 384 + }, + { + "path": "dist/cli/commands/inputSource.js", + "size": 4844, + "mode": 384 + }, + { + "path": "dist/cli/commands/inputSource.js.map", + "size": 4199, + "mode": 384 + }, + { + "path": "dist/cli/commands/inspect.d.ts", + "size": 284, + "mode": 384 + }, + { + "path": "dist/cli/commands/inspect.d.ts.map", + "size": 344, + "mode": 384 + }, + { + "path": "dist/cli/commands/inspect.js", + "size": 6953, + "mode": 384 + }, + { + "path": "dist/cli/commands/inspect.js.map", + "size": 6299, + "mode": 384 + }, + { + "path": "dist/cli/commands/list.d.ts", + "size": 400, + "mode": 384 + }, + { + "path": "dist/cli/commands/list.d.ts.map", + "size": 437, + "mode": 384 + }, + { + "path": "dist/cli/commands/list.js", + "size": 523, + "mode": 384 + }, + { + "path": "dist/cli/commands/list.js.map", + "size": 666, + "mode": 384 + }, + { + "path": "dist/cli/commands/mark.d.ts", + "size": 348, + "mode": 384 + }, + { + "path": "dist/cli/commands/mark.d.ts.map", + "size": 401, + "mode": 384 + }, + { + "path": "dist/cli/commands/mark.js", + "size": 2249, + "mode": 384 + }, + { + "path": "dist/cli/commands/mark.js.map", + "size": 1982, + "mode": 384 + }, + { + "path": "dist/cli/commands/paste.d.ts", + "size": 388, + "mode": 384 + }, + { + "path": "dist/cli/commands/paste.d.ts.map", + "size": 468, + "mode": 384 + }, + { + "path": "dist/cli/commands/paste.js", + "size": 2241, + "mode": 384 + }, + { + "path": "dist/cli/commands/paste.js.map", + "size": 1927, + "mode": 384 + }, + { + "path": "dist/cli/commands/record-export.d.ts", + "size": 377, + "mode": 384 + }, + { + "path": "dist/cli/commands/record-export.d.ts.map", + "size": 479, + "mode": 384 + }, + { + "path": "dist/cli/commands/record-export.js", + "size": 12960, + "mode": 384 + }, + { + "path": "dist/cli/commands/record-export.js.map", + "size": 9891, + "mode": 384 + }, + { + "path": "dist/cli/commands/resize.d.ts", + "size": 388, + "mode": 384 + }, + { + "path": "dist/cli/commands/resize.d.ts.map", + "size": 465, + "mode": 384 + }, + { + "path": "dist/cli/commands/resize.js", + "size": 2401, + "mode": 384 + }, + { + "path": "dist/cli/commands/resize.js.map", + "size": 2122, + "mode": 384 + }, + { + "path": "dist/cli/commands/run.d.ts", + "size": 365, + "mode": 384 + }, + { + "path": "dist/cli/commands/run.d.ts.map", + "size": 448, + "mode": 384 + }, + { + "path": "dist/cli/commands/run.js", + "size": 3624, + "mode": 384 + }, + { + "path": "dist/cli/commands/run.js.map", + "size": 3231, + "mode": 384 + }, + { + "path": "dist/cli/commands/screenshot.d.ts", + "size": 338, + "mode": 384 + }, + { + "path": "dist/cli/commands/screenshot.d.ts.map", + "size": 412, + "mode": 384 + }, + { + "path": "dist/cli/commands/screenshot.js", + "size": 8439, + "mode": 384 + }, + { + "path": "dist/cli/commands/screenshot.js.map", + "size": 6884, + "mode": 384 + }, + { + "path": "dist/cli/commands/send-keys.d.ts", + "size": 362, + "mode": 384 + }, + { + "path": "dist/cli/commands/send-keys.d.ts.map", + "size": 420, + "mode": 384 + }, + { + "path": "dist/cli/commands/send-keys.js", + "size": 2483, + "mode": 384 + }, + { + "path": "dist/cli/commands/send-keys.js.map", + "size": 2160, + "mode": 384 + }, + { + "path": "dist/cli/commands/signal.d.ts", + "size": 380, + "mode": 384 + }, + { + "path": "dist/cli/commands/signal.d.ts.map", + "size": 443, + "mode": 384 + }, + { + "path": "dist/cli/commands/signal.js", + "size": 2333, + "mode": 384 + }, + { + "path": "dist/cli/commands/signal.js.map", + "size": 2012, + "mode": 384 + }, + { + "path": "dist/cli/commands/snapshot.d.ts", + "size": 368, + "mode": 384 + }, + { + "path": "dist/cli/commands/snapshot.d.ts.map", + "size": 441, + "mode": 384 + }, + { + "path": "dist/cli/commands/snapshot.js", + "size": 8746, + "mode": 384 + }, + { + "path": "dist/cli/commands/snapshot.js.map", + "size": 7554, + "mode": 384 + }, + { + "path": "dist/cli/commands/type.d.ts", + "size": 414, + "mode": 384 + }, + { + "path": "dist/cli/commands/type.d.ts.map", + "size": 497, + "mode": 384 + }, + { + "path": "dist/cli/commands/type.js", + "size": 2329, + "mode": 384 + }, + { + "path": "dist/cli/commands/type.js.map", + "size": 2024, + "mode": 384 + }, + { + "path": "dist/cli/commands/version.d.ts", + "size": 729, + "mode": 384 + }, + { + "path": "dist/cli/commands/version.d.ts.map", + "size": 761, + "mode": 384 + }, + { + "path": "dist/cli/commands/version.js", + "size": 2346, + "mode": 384 + }, + { + "path": "dist/cli/commands/version.js.map", + "size": 2077, + "mode": 384 + }, + { + "path": "dist/cli/commands/wait.d.ts", + "size": 540, + "mode": 384 + }, + { + "path": "dist/cli/commands/wait.d.ts.map", + "size": 613, + "mode": 384 + }, + { + "path": "dist/cli/commands/wait.js", + "size": 12009, + "mode": 384 + }, + { + "path": "dist/cli/commands/wait.js.map", + "size": 10091, + "mode": 384 + }, + { + "path": "dist/cli/context.d.ts", + "size": 1151, + "mode": 384 + }, + { + "path": "dist/cli/context.d.ts.map", + "size": 1179, + "mode": 384 + }, + { + "path": "dist/cli/context.js", + "size": 3625, + "mode": 384 + }, + { + "path": "dist/cli/context.js.map", + "size": 3263, + "mode": 384 + }, + { + "path": "dist/cli/errors.d.ts", + "size": 355, + "mode": 384 + }, + { + "path": "dist/cli/errors.d.ts.map", + "size": 449, + "mode": 384 + }, + { + "path": "dist/cli/errors.js", + "size": 370, + "mode": 384 + }, + { + "path": "dist/cli/errors.js.map", + "size": 494, + "mode": 384 + }, + { + "path": "dist/cli/exitCodes.d.ts", + "size": 103, + "mode": 384 + }, + { + "path": "dist/cli/exitCodes.d.ts.map", + "size": 174, + "mode": 384 + }, + { + "path": "dist/cli/exitCodes.js", + "size": 973, + "mode": 384 + }, + { + "path": "dist/cli/exitCodes.js.map", + "size": 1108, + "mode": 384 + }, + { + "path": "dist/cli/main.d.ts", + "size": 65, + "mode": 384 + }, + { + "path": "dist/cli/main.d.ts.map", + "size": 109, + "mode": 384 + }, + { + "path": "dist/cli/main.js", + "size": 18019, + "mode": 384 + }, + { + "path": "dist/cli/main.js.map", + "size": 14572, + "mode": 384 + }, + { + "path": "dist/cli/output.d.ts", + "size": 616, + "mode": 384 + }, + { + "path": "dist/cli/output.d.ts.map", + "size": 664, + "mode": 384 + }, + { + "path": "dist/cli/output.js", + "size": 1293, + "mode": 384 + }, + { + "path": "dist/cli/output.js.map", + "size": 1417, + "mode": 384 + }, + { + "path": "dist/config/defaults.d.ts", + "size": 487, + "mode": 384 + }, + { + "path": "dist/config/defaults.d.ts.map", + "size": 429, + "mode": 384 + }, + { + "path": "dist/config/defaults.js", + "size": 483, + "mode": 384 + }, + { + "path": "dist/config/defaults.js.map", + "size": 558, + "mode": 384 + }, + { + "path": "dist/config/resolveConfig.d.ts", + "size": 1036, + "mode": 384 + }, + { + "path": "dist/config/resolveConfig.d.ts.map", + "size": 698, + "mode": 384 + }, + { + "path": "dist/config/resolveConfig.js", + "size": 2613, + "mode": 384 + }, + { + "path": "dist/config/resolveConfig.js.map", + "size": 2788, + "mode": 384 + }, + { + "path": "dist/export/asciicast.d.ts", + "size": 710, + "mode": 384 + }, + { + "path": "dist/export/asciicast.d.ts.map", + "size": 787, + "mode": 384 + }, + { + "path": "dist/export/asciicast.js", + "size": 3590, + "mode": 384 + }, + { + "path": "dist/export/asciicast.js.map", + "size": 3262, + "mode": 384 + }, + { + "path": "dist/export/webm.d.ts", + "size": 1122, + "mode": 384 + }, + { + "path": "dist/export/webm.d.ts.map", + "size": 1073, + "mode": 384 + }, + { + "path": "dist/export/webm.js", + "size": 5696, + "mode": 384 + }, + { + "path": "dist/export/webm.js.map", + "size": 5122, + "mode": 384 + }, + { + "path": "dist/host/eventLog.d.ts", + "size": 2899, + "mode": 384 + }, + { + "path": "dist/host/eventLog.d.ts.map", + "size": 2164, + "mode": 384 + }, + { + "path": "dist/host/eventLog.js", + "size": 10623, + "mode": 384 + }, + { + "path": "dist/host/eventLog.js.map", + "size": 9860, + "mode": 384 + }, + { + "path": "dist/host/hostMain.d.ts", + "size": 680, + "mode": 384 + }, + { + "path": "dist/host/hostMain.d.ts.map", + "size": 411, + "mode": 384 + }, + { + "path": "dist/host/hostMain.js", + "size": 42048, + "mode": 384 + }, + { + "path": "dist/host/hostMain.js.map", + "size": 31769, + "mode": 384 + }, + { + "path": "dist/host/lifecycle.d.ts", + "size": 1105, + "mode": 384 + }, + { + "path": "dist/host/lifecycle.d.ts.map", + "size": 1272, + "mode": 384 + }, + { + "path": "dist/host/lifecycle.js", + "size": 16626, + "mode": 384 + }, + { + "path": "dist/host/lifecycle.js.map", + "size": 15418, + "mode": 384 + }, + { + "path": "dist/host/renderer.d.ts", + "size": 1124, + "mode": 384 + }, + { + "path": "dist/host/renderer.d.ts.map", + "size": 980, + "mode": 384 + }, + { + "path": "dist/host/renderer.js", + "size": 5911, + "mode": 384 + }, + { + "path": "dist/host/renderer.js.map", + "size": 5082, + "mode": 384 + }, + { + "path": "dist/host/replay.d.ts", + "size": 450, + "mode": 384 + }, + { + "path": "dist/host/replay.d.ts.map", + "size": 468, + "mode": 384 + }, + { + "path": "dist/host/replay.js", + "size": 3887, + "mode": 384 + }, + { + "path": "dist/host/replay.js.map", + "size": 3723, + "mode": 384 + }, + { + "path": "dist/host/rpcClient.d.ts", + "size": 180, + "mode": 384 + }, + { + "path": "dist/host/rpcClient.d.ts.map", + "size": 288, + "mode": 384 + }, + { + "path": "dist/host/rpcClient.js", + "size": 7860, + "mode": 384 + }, + { + "path": "dist/host/rpcClient.js.map", + "size": 6159, + "mode": 384 + }, + { + "path": "dist/host/rpcServer.d.ts", + "size": 513, + "mode": 384 + }, + { + "path": "dist/host/rpcServer.d.ts.map", + "size": 559, + "mode": 384 + }, + { + "path": "dist/host/rpcServer.js", + "size": 9355, + "mode": 384 + }, + { + "path": "dist/host/rpcServer.js.map", + "size": 8933, + "mode": 384 + }, + { + "path": "dist/host/sessionState.d.ts", + "size": 659, + "mode": 384 + }, + { + "path": "dist/host/sessionState.d.ts.map", + "size": 678, + "mode": 384 + }, + { + "path": "dist/host/sessionState.js", + "size": 4175, + "mode": 384 + }, + { + "path": "dist/host/sessionState.js.map", + "size": 3577, + "mode": 384 + }, + { + "path": "dist/index.d.ts", + "size": 745, + "mode": 384 + }, + { + "path": "dist/index.d.ts.map", + "size": 603, + "mode": 384 + }, + { + "path": "dist/index.js", + "size": 44, + "mode": 384 + }, + { + "path": "dist/index.js.map", + "size": 102, + "mode": 384 + }, + { + "path": "dist/protocol/envelope.d.ts", + "size": 754, + "mode": 384 + }, + { + "path": "dist/protocol/envelope.d.ts.map", + "size": 806, + "mode": 384 + }, + { + "path": "dist/protocol/envelope.js", + "size": 383, + "mode": 384 + }, + { + "path": "dist/protocol/envelope.js.map", + "size": 440, + "mode": 384 + }, + { + "path": "dist/protocol/errors.d.ts", + "size": 1506, + "mode": 384 + }, + { + "path": "dist/protocol/errors.d.ts.map", + "size": 616, + "mode": 384 + }, + { + "path": "dist/protocol/errors.js", + "size": 2751, + "mode": 384 + }, + { + "path": "dist/protocol/errors.js.map", + "size": 2115, + "mode": 384 + }, + { + "path": "dist/protocol/messages.d.ts", + "size": 20763, + "mode": 384 + }, + { + "path": "dist/protocol/messages.d.ts.map", + "size": 4751, + "mode": 384 + }, + { + "path": "dist/protocol/messages.js", + "size": 6897, + "mode": 384 + }, + { + "path": "dist/protocol/messages.js.map", + "size": 7119, + "mode": 384 + }, + { + "path": "dist/protocol/schemas.d.ts", + "size": 15897, + "mode": 384 + }, + { + "path": "dist/protocol/schemas.d.ts.map", + "size": 3902, + "mode": 384 + }, + { + "path": "dist/protocol/schemas.js", + "size": 10742, + "mode": 384 + }, + { + "path": "dist/protocol/schemas.js.map", + "size": 10562, + "mode": 384 + }, + { + "path": "dist/protocol/terminationCategory.d.ts", + "size": 254, + "mode": 384 + }, + { + "path": "dist/protocol/terminationCategory.d.ts.map", + "size": 297, + "mode": 384 + }, + { + "path": "dist/protocol/terminationCategory.js", + "size": 1060, + "mode": 384 + }, + { + "path": "dist/protocol/terminationCategory.js.map", + "size": 827, + "mode": 384 + }, + { + "path": "dist/pty/createPty.d.ts", + "size": 298, + "mode": 384 + }, + { + "path": "dist/pty/createPty.d.ts.map", + "size": 426, + "mode": 384 + }, + { + "path": "dist/pty/createPty.js", + "size": 1086, + "mode": 384 + }, + { + "path": "dist/pty/createPty.js.map", + "size": 1175, + "mode": 384 + }, + { + "path": "dist/pty/keyEncoder.d.ts", + "size": 100, + "mode": 384 + }, + { + "path": "dist/pty/keyEncoder.d.ts.map", + "size": 175, + "mode": 384 + }, + { + "path": "dist/pty/keyEncoder.js", + "size": 6648, + "mode": 384 + }, + { + "path": "dist/pty/keyEncoder.js.map", + "size": 6721, + "mode": 384 + }, + { + "path": "dist/pty/pasteEncoder.d.ts", + "size": 101, + "mode": 384 + }, + { + "path": "dist/pty/pasteEncoder.d.ts.map", + "size": 177, + "mode": 384 + }, + { + "path": "dist/pty/pasteEncoder.js", + "size": 301, + "mode": 384 + }, + { + "path": "dist/pty/pasteEncoder.js.map", + "size": 358, + "mode": 384 + }, + { + "path": "dist/renderer/backend.d.ts", + "size": 2120, + "mode": 384 + }, + { + "path": "dist/renderer/backend.d.ts.map", + "size": 1629, + "mode": 384 + }, + { + "path": "dist/renderer/backend.js", + "size": 46, + "mode": 384 + }, + { + "path": "dist/renderer/backend.js.map", + "size": 118, + "mode": 384 + }, + { + "path": "dist/renderer/browserPath.d.ts", + "size": 1394, + "mode": 384 + }, + { + "path": "dist/renderer/browserPath.d.ts.map", + "size": 583, + "mode": 384 + }, + { + "path": "dist/renderer/browserPath.js", + "size": 2997, + "mode": 384 + }, + { + "path": "dist/renderer/browserPath.js.map", + "size": 2117, + "mode": 384 + }, + { + "path": "dist/renderer/bundledFont.d.ts", + "size": 1253, + "mode": 384 + }, + { + "path": "dist/renderer/bundledFont.d.ts.map", + "size": 900, + "mode": 384 + }, + { + "path": "dist/renderer/bundledFont.js", + "size": 3412, + "mode": 384 + }, + { + "path": "dist/renderer/bundledFont.js.map", + "size": 2700, + "mode": 384 + }, + { + "path": "dist/renderer/capabilities.d.ts", + "size": 2962, + "mode": 384 + }, + { + "path": "dist/renderer/capabilities.d.ts.map", + "size": 1401, + "mode": 384 + }, + { + "path": "dist/renderer/capabilities.js", + "size": 10072, + "mode": 384 + }, + { + "path": "dist/renderer/capabilities.js.map", + "size": 7611, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/assets/FONT-LICENSE.txt", + "size": 398, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/assets/JetBrainsMono-Regular-latin.woff2", + "size": 21168, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/assets/SymbolsNerdFontMono-Regular.ttf", + "size": 2507556, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/backend.d.ts", + "size": 2108, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/backend.d.ts.map", + "size": 1797, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/backend.js", + "size": 73829, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/backend.js.map", + "size": 40446, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/index.d.ts", + "size": 85, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/index.d.ts.map", + "size": 171, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/index.js", + "size": 83, + "mode": 384 + }, + { + "path": "dist/renderer/ghosttyWeb/index.js.map", + "size": 169, + "mode": 384 + }, + { + "path": "dist/renderer/index.d.ts", + "size": 714, + "mode": 384 + }, + { + "path": "dist/renderer/index.d.ts.map", + "size": 607, + "mode": 384 + }, + { + "path": "dist/renderer/index.js", + "size": 438, + "mode": 384 + }, + { + "path": "dist/renderer/index.js.map", + "size": 401, + "mode": 384 + }, + { + "path": "dist/renderer/profiles.d.ts", + "size": 567, + "mode": 384 + }, + { + "path": "dist/renderer/profiles.d.ts.map", + "size": 434, + "mode": 384 + }, + { + "path": "dist/renderer/profiles.js", + "size": 6091, + "mode": 384 + }, + { + "path": "dist/renderer/profiles.js.map", + "size": 5051, + "mode": 384 + }, + { + "path": "dist/renderer/types.d.ts", + "size": 8390, + "mode": 384 + }, + { + "path": "dist/renderer/types.d.ts.map", + "size": 1335, + "mode": 384 + }, + { + "path": "dist/renderer/types.js", + "size": 7545, + "mode": 384 + }, + { + "path": "dist/renderer/types.js.map", + "size": 7452, + "mode": 384 + }, + { + "path": "dist/replay/offlineReplay.d.ts", + "size": 742, + "mode": 384 + }, + { + "path": "dist/replay/offlineReplay.d.ts.map", + "size": 755, + "mode": 384 + }, + { + "path": "dist/replay/offlineReplay.js", + "size": 3757, + "mode": 384 + }, + { + "path": "dist/replay/offlineReplay.js.map", + "size": 3303, + "mode": 384 + }, + { + "path": "dist/storage/artifactHealth.d.ts", + "size": 213, + "mode": 384 + }, + { + "path": "dist/storage/artifactHealth.d.ts.map", + "size": 259, + "mode": 384 + }, + { + "path": "dist/storage/artifactHealth.js", + "size": 2852, + "mode": 384 + }, + { + "path": "dist/storage/artifactHealth.js.map", + "size": 2517, + "mode": 384 + }, + { + "path": "dist/storage/artifactManifest.d.ts", + "size": 1797, + "mode": 384 + }, + { + "path": "dist/storage/artifactManifest.d.ts.map", + "size": 768, + "mode": 384 + }, + { + "path": "dist/storage/artifactManifest.js", + "size": 5955, + "mode": 384 + }, + { + "path": "dist/storage/artifactManifest.js.map", + "size": 5090, + "mode": 384 + }, + { + "path": "dist/storage/artifactPaths.d.ts", + "size": 549, + "mode": 384 + }, + { + "path": "dist/storage/artifactPaths.d.ts.map", + "size": 583, + "mode": 384 + }, + { + "path": "dist/storage/artifactPaths.js", + "size": 3418, + "mode": 384 + }, + { + "path": "dist/storage/artifactPaths.js.map", + "size": 3114, + "mode": 384 + }, + { + "path": "dist/storage/home.d.ts", + "size": 206, + "mode": 384 + }, + { + "path": "dist/storage/home.d.ts.map", + "size": 232, + "mode": 384 + }, + { + "path": "dist/storage/home.js", + "size": 1380, + "mode": 384 + }, + { + "path": "dist/storage/home.js.map", + "size": 1379, + "mode": 384 + }, + { + "path": "dist/storage/manifests.d.ts", + "size": 1239, + "mode": 384 + }, + { + "path": "dist/storage/manifests.d.ts.map", + "size": 1280, + "mode": 384 + }, + { + "path": "dist/storage/manifests.js", + "size": 4240, + "mode": 384 + }, + { + "path": "dist/storage/manifests.js.map", + "size": 3962, + "mode": 384 + }, + { + "path": "dist/storage/sessionPaths.d.ts", + "size": 333, + "mode": 384 + }, + { + "path": "dist/storage/sessionPaths.d.ts.map", + "size": 368, + "mode": 384 + }, + { + "path": "dist/storage/sessionPaths.js", + "size": 1965, + "mode": 384 + }, + { + "path": "dist/storage/sessionPaths.js.map", + "size": 1795, + "mode": 384 + }, + { + "path": "dist/tools/index.d.ts", + "size": 213, + "mode": 384 + }, + { + "path": "dist/tools/index.d.ts.map", + "size": 145, + "mode": 384 + }, + { + "path": "dist/tools/index.js", + "size": 211, + "mode": 384 + }, + { + "path": "dist/tools/index.js.map", + "size": 143, + "mode": 384 + }, + { + "path": "dist/tools/review-bundle.d.ts", + "size": 3863, + "mode": 384 + }, + { + "path": "dist/tools/review-bundle.d.ts.map", + "size": 2210, + "mode": 384 + }, + { + "path": "dist/tools/review-bundle.js", + "size": 34347, + "mode": 384 + }, + { + "path": "dist/tools/review-bundle.js.map", + "size": 29580, + "mode": 384 + }, + { + "path": "dist/tools/validate-bundle.d.ts", + "size": 1021, + "mode": 384 + }, + { + "path": "dist/tools/validate-bundle.d.ts.map", + "size": 824, + "mode": 384 + }, + { + "path": "dist/tools/validate-bundle.js", + "size": 8286, + "mode": 384 + }, + { + "path": "dist/tools/validate-bundle.js.map", + "size": 7747, + "mode": 384 + }, + { + "path": "dist/util/assert.d.ts", + "size": 298, + "mode": 384 + }, + { + "path": "dist/util/assert.d.ts.map", + "size": 365, + "mode": 384 + }, + { + "path": "dist/util/assert.js", + "size": 361, + "mode": 384 + }, + { + "path": "dist/util/assert.js.map", + "size": 492, + "mode": 384 + }, + { + "path": "dist/util/logger.d.ts", + "size": 1168, + "mode": 384 + }, + { + "path": "dist/util/logger.d.ts.map", + "size": 1221, + "mode": 384 + }, + { + "path": "dist/util/logger.js", + "size": 2765, + "mode": 384 + }, + { + "path": "dist/util/logger.js.map", + "size": 3055, + "mode": 384 + }, + { + "path": "package.json", + "size": 2135, + "mode": 384 + }, + { + "path": "skills/agent-terminal/SKILL.md", + "size": 5147, + "mode": 384 + } + ], + "entryCount": 270, + "bundled": [] + } +] diff --git a/dogfood/install-flows/tarball/record-asciicast.json b/dogfood/install-flows/tarball/record-asciicast.json new file mode 100644 index 0000000..931a1aa --- /dev/null +++ b/dogfood/install-flows/tarball/record-asciicast.json @@ -0,0 +1,23 @@ +{ + "ok": true, + "command": "record export", + "timestamp": "2026-04-07T20:30:33.556Z", + "result": { + "sessionId": "01KNMT70YKGVN6PR3MWWAK7MMM", + "format": "asciicast", + "artifactPath": "/tmp/tmp.0v4LnZJ3BC/sessions/01KNMT70YKGVN6PR3MWWAK7MMM/artifacts/recording-22-asciicast.cast", + "bytes": 8963, + "sha256": "fa20d495273b2959b738d84827d810f1bbc4d7818e4c73468e79631993e297a4", + "capturedAtSeq": 22, + "durationMs": 9348, + "metadata": { + "width": 140, + "height": 40, + "title": "01KNMT70YKGVN6PR3MWWAK7MMM", + "timestamp": 1775593817, + "outputEventCount": 20, + "resizeEventCount": 0, + "markerCount": 0 + } + } +} diff --git a/dogfood/install-flows/tarball/record-webm.json b/dogfood/install-flows/tarball/record-webm.json new file mode 100644 index 0000000..5e10d42 --- /dev/null +++ b/dogfood/install-flows/tarball/record-webm.json @@ -0,0 +1,23 @@ +{ + "ok": true, + "command": "record export", + "timestamp": "2026-04-07T20:30:32.856Z", + "result": { + "sessionId": "01KNMT70YKGVN6PR3MWWAK7MMM", + "format": "webm", + "artifactPath": "/tmp/tmp.0v4LnZJ3BC/sessions/01KNMT70YKGVN6PR3MWWAK7MMM/artifacts/recording-22-webm.webm", + "bytes": 253650, + "sha256": "2e3454a54872dcc1373fe77b7ccf9e7fafc186b0052966e05c3fe484862def8c", + "capturedAtSeq": 22, + "durationMs": 9348, + "metadata": { + "width": 140, + "height": 40, + "profileName": "reference-dark", + "renderProfileHash": "8ffed6af301ec7c0e6b69599c3be0d1d12096f9fcdfc59d0bbb4cc474d64c53d", + "timingMode": "accelerated", + "outputEventCount": 20, + "resizeEventCount": 0 + } + } +} diff --git a/dogfood/install-flows/tarball/session-id.txt b/dogfood/install-flows/tarball/session-id.txt new file mode 100644 index 0000000..c3cb50e --- /dev/null +++ b/dogfood/install-flows/tarball/session-id.txt @@ -0,0 +1 @@ +01KNMT70YKGVN6PR3MWWAK7MMM diff --git a/dogfood/install-flows/tarball/tarball-path.txt b/dogfood/install-flows/tarball/tarball-path.txt new file mode 100644 index 0000000..fcc08cb --- /dev/null +++ b/dogfood/install-flows/tarball/tarball-path.txt @@ -0,0 +1 @@ +/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball-artifact/agent-terminal-0.1.0.tgz diff --git a/dogfood/install-flows/tarball/version-run.json b/dogfood/install-flows/tarball/version-run.json new file mode 100644 index 0000000..b5400ab --- /dev/null +++ b/dogfood/install-flows/tarball/version-run.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "run", + "timestamp": "2026-04-07T20:30:24.478Z", + "result": { + "accepted": true, + "completed": true, + "timedOut": false, + "seq": 8, + "durationMs": 362, + "marker": "__AT_MARKER_2c25feae98d4433fb02d6dedda1398a8__" + } +} diff --git a/dogfood/install-flows/tarball/version-screenshot.json b/dogfood/install-flows/tarball/version-screenshot.json new file mode 100644 index 0000000..3fa2374 --- /dev/null +++ b/dogfood/install-flows/tarball/version-screenshot.json @@ -0,0 +1,20 @@ +{ + "ok": true, + "command": "screenshot", + "timestamp": "2026-04-07T20:30:26.381Z", + "result": { + "sessionId": "01KNMT70YKGVN6PR3MWWAK7MMM", + "capturedAtSeq": 13, + "profileName": "reference-dark", + "cols": 140, + "rows": 40, + "artifactPath": "/tmp/tmp.0v4LnZJ3BC/sessions/01KNMT70YKGVN6PR3MWWAK7MMM/artifacts/screenshot-13-reference-dark.png", + "pngSizeBytes": 53892, + "cursorVisible": false, + "rendererBackend": "ghostty-web", + "pixelWidth": 1120, + "pixelHeight": 640, + "sha256": "d014e9f556bb4d60a207d89da8f563c5e7a1958056acff713f0d7a85b7f241d5", + "renderProfileHash": "8ffed6af301ec7c0e6b69599c3be0d1d12096f9fcdfc59d0bbb4cc474d64c53d" + } +} diff --git a/dogfood/install-flows/tarball/version-step.sh b/dogfood/install-flows/tarball/version-step.sh new file mode 100644 index 0000000..c5399a6 --- /dev/null +++ b/dogfood/install-flows/tarball/version-step.sh @@ -0,0 +1,5 @@ +set -euo pipefail +printf '\033c' +echo '# tarball version' +cat "/home/coder/.mux/src/agent-terminal/npm-install-5r2j/dogfood/install-flows/tarball/version.json" +echo '__DOGFOOD_DONE__ version' diff --git a/dogfood/install-flows/tarball/version-wait.json b/dogfood/install-flows/tarball/version-wait.json new file mode 100644 index 0000000..b020ef3 --- /dev/null +++ b/dogfood/install-flows/tarball/version-wait.json @@ -0,0 +1,13 @@ +{ + "ok": true, + "command": "wait", + "timestamp": "2026-04-07T20:30:25.444Z", + "result": { + "matched": true, + "timedOut": false, + "matchedText": "__DOGFOOD_DONE__ version", + "cursorRow": 39, + "cursorCol": 10, + "capturedAtSeq": 13 + } +} diff --git a/dogfood/install-flows/tarball/version.json b/dogfood/install-flows/tarball/version.json new file mode 100644 index 0000000..e776080 --- /dev/null +++ b/dogfood/install-flows/tarball/version.json @@ -0,0 +1,37 @@ +{ + "ok": true, + "command": "version", + "timestamp": "2026-04-07T20:24:41.640Z", + "result": { + "cliVersion": "0.1.0", + "protocolVersion": "0.1.0", + "rendererBackends": ["ghostty-web"], + "runtime": { + "node": "v24.14.0", + "platform": "linux", + "arch": "x64" + }, + "capabilities": [ + { + "name": "snapshot", + "status": "available" + }, + { + "name": "wait", + "status": "available" + }, + { + "name": "screenshot", + "status": "available" + }, + { + "name": "record-export-asciicast", + "status": "available" + }, + { + "name": "record-export-webm", + "status": "available" + } + ] + } +} diff --git a/dogfood/install-flows/tarball/version.png b/dogfood/install-flows/tarball/version.png new file mode 100644 index 0000000..c127c6b Binary files /dev/null and b/dogfood/install-flows/tarball/version.png differ diff --git a/mise.toml b/mise.toml index b721b36..c8b26b7 100644 --- a/mise.toml +++ b/mise.toml @@ -23,6 +23,10 @@ run = "npm run build" sources = ["src/**/*.ts", "tsconfig.json", "tsconfig.build.json", "package.json"] outputs = ["dist/**/*.js", "dist/**/*.d.ts", "dist/**/*.map"] +[tasks.install-smoke] +description = "Validate the tarball route and check the current git-install caveat" +run = "npm run smoke:install -- --skip-build" + [tasks.typecheck] description = "Typecheck" run = "npm run typecheck" @@ -75,4 +79,4 @@ sources = [ [tasks.ci] description = "Run CI checks" -run = "mise run format-check && mise run lint && mise run typecheck && mise run test && mise run build" +run = "mise run format-check && mise run lint && mise run typecheck && mise run test && mise run build && mise run install-smoke" diff --git a/package.json b/package.json index 8f96aab..e66371e 100644 --- a/package.json +++ b/package.json @@ -34,13 +34,16 @@ "intent:validate": "npx @tanstack/intent@latest validate", "lint": "eslint src test vitest.config.ts --max-warnings=0", "lint:fix": "eslint src test vitest.config.ts --fix", + "pack:private": "npm run build && npm pack --json --ignore-scripts", + "prepare": "npm run build", "prepublishOnly": "npm run verify", "review-bundle": "tsx src/tools/review-bundle.ts", + "smoke:install": "node ./scripts/smoke-install.mjs", "test": "vitest run", "test:watch": "vitest", "typecheck": "tsc -p tsconfig.json --noEmit", "validate-bundle": "tsx src/tools/validate-bundle.ts", - "verify": "npm run format:check && npm run lint && npm run typecheck && npm run test && npm run build", + "verify": "npm run format:check && npm run lint && npm run typecheck && npm run test && npm run build && npm run smoke:install -- --skip-build", "version:json": "tsx src/cli/main.ts version --json" }, "devDependencies": { diff --git a/scripts/smoke-install.mjs b/scripts/smoke-install.mjs new file mode 100755 index 0000000..1094b2a --- /dev/null +++ b/scripts/smoke-install.mjs @@ -0,0 +1,515 @@ +#!/usr/bin/env node +import assert from 'node:assert/strict'; +import { spawnSync } from 'node:child_process'; +import { constants as fsConstants } from 'node:fs'; +import { + access, + cp, + mkdir, + mkdtemp, + readFile, + readdir, + rm, + stat, +} from 'node:fs/promises'; +import { homedir, tmpdir } from 'node:os'; +import { basename, delimiter, join, relative, resolve } from 'node:path'; +import process from 'node:process'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const projectRoot = resolve(fileURLToPath(new URL('..', import.meta.url))); +const npmCliPath = process.env.npm_execpath; +const supportedArgs = new Set(['--skip-build']); + +for (const argument of process.argv.slice(2)) { + assert(supportedArgs.has(argument), `unsupported argument: ${argument}`); +} + +const skipBuild = process.argv.includes('--skip-build'); + +const packageJson = JSON.parse( + await readFile(join(projectRoot, 'package.json'), 'utf8'), +); +const packageName = packageJson.name; +const packageVersion = packageJson.version; +const packageBins = packageJson.bin; + +assert.equal( + typeof packageName, + 'string', + 'package.json name must be a string', +); +assert.equal( + typeof packageVersion, + 'string', + 'package.json version must be a string', +); +assert( + typeof packageBins === 'object' && packageBins !== null, + 'package.json bin must be an object', +); + +const [binName] = Object.keys(packageBins); +assert(typeof binName === 'string' && binName.length > 0, 'bin name missing'); + +const tempRoot = await mkdtemp(join(tmpdir(), 'agent-terminal-install-smoke-')); + +function logStep(message) { + assert(message.length > 0, 'log messages must be non-empty'); + process.stdout.write(`${message}\n`); +} + +// Some dev environments inject `mise activate` into npm build subprocesses. +// Trust the current repo plus temp roots so packaging smoke reflects the +// package behavior instead of unrelated local shell trust prompts. +function getTrustedConfigPaths() { + const trustedPaths = new Set(); + const existingPaths = process.env.MISE_TRUSTED_CONFIG_PATHS; + + if (typeof existingPaths === 'string' && existingPaths.length > 0) { + for (const trustedPath of existingPaths.split(delimiter)) { + if (trustedPath.length > 0) { + trustedPaths.add(trustedPath); + } + } + } + + const npmCachePath = + process.env.npm_config_cache ?? join(process.env.HOME ?? homedir(), '.npm'); + trustedPaths.add(npmCachePath); + trustedPaths.add(projectRoot); + trustedPaths.add(tempRoot); + trustedPaths.add(tmpdir()); + return [...trustedPaths].join(delimiter); +} + +function sanitizeInheritedPath(pathValue) { + assert(typeof pathValue === 'string', 'PATH must be a string'); + assert(pathValue.length > 0, 'PATH must not be empty'); + + const sanitizedEntries = pathValue + .split(delimiter) + .filter((entry) => entry.length > 0) + .filter( + (entry) => + !entry.endsWith(`${join('node_modules', '.bin')}`) && + !entry.endsWith('node-gyp-bin'), + ); + + assert( + sanitizedEntries.length > 0, + 'sanitized PATH must retain at least one executable directory', + ); + return sanitizedEntries.join(delimiter); +} + +function getDefaultEnv() { + return { + ...process.env, + PATH: sanitizeInheritedPath(process.env.PATH ?? ''), + MISE_TRUSTED_CONFIG_PATHS: getTrustedConfigPaths(), + npm_config_audit: 'false', + npm_config_fund: 'false', + npm_config_update_notifier: 'false', + }; +} + +function formatCommand(command, args) { + return [command, ...args].join(' '); +} + +function run(command, args, options = {}) { + const { + cwd = projectRoot, + env = getDefaultEnv(), + expectedStatus = 0, + allowFailure = false, + } = options; + const result = spawnSync(command, args, { + cwd, + env, + encoding: 'utf8', + }); + + assert(result.error === undefined, result.error?.message ?? 'spawn failed'); + if (!allowFailure) { + assert.equal( + result.status, + expectedStatus, + [ + `command failed: ${formatCommand(command, args)}`, + `cwd: ${cwd}`, + `expected exit code: ${String(expectedStatus)}`, + `actual exit code: ${String(result.status)}`, + result.stdout.length === 0 ? '' : `stdout:\n${result.stdout}`, + result.stderr.length === 0 ? '' : `stderr:\n${result.stderr}`, + ] + .filter((line) => line.length > 0) + .join('\n\n'), + ); + } + + return result; +} + +function runNpm(args, options = {}) { + if (typeof npmCliPath === 'string' && npmCliPath.length > 0) { + return run(process.execPath, [npmCliPath, ...args], options); + } + + return run('npm', args, options); +} + +function isKnownGitInstallCaveat(result) { + const combinedOutput = `${result.stdout}\n${result.stderr}`; + return ( + combinedOutput.includes('node-pty') && + (combinedOutput.includes('TAR_ENTRY_ERROR') || + combinedOutput.includes('spawn sh ENOENT') || + combinedOutput.includes('spawn /bin/sh ENOENT') || + combinedOutput.includes('uv_cwd') || + combinedOutput.includes('git dep preparation failed')) + ); +} + +function parseJsonOutput(stdout, description) { + assert(stdout.trim().length > 0, `${description} must not be empty`); + + try { + return JSON.parse(stdout); + } catch (error) { + throw new Error(`${description} was not valid JSON`, { cause: error }); + } +} + +async function listRelativeFiles(directory, root = directory) { + const entries = await readdir(directory, { withFileTypes: true }); + const files = []; + + for (const entry of entries) { + const absolutePath = join(directory, entry.name); + if (entry.isDirectory()) { + files.push(...(await listRelativeFiles(absolutePath, root))); + continue; + } + + assert(entry.isFile(), `expected file entry under ${directory}`); + files.push(relative(root, absolutePath).replaceAll('\\', '/')); + } + + return files.sort(); +} + +async function assertPathExists(path, description, mode = fsConstants.F_OK) { + await access(path, mode).catch((error) => { + throw new Error(`${description} missing at ${path}`, { cause: error }); + }); +} + +async function assertPackagePaths(packageRoot, requiredPaths, label) { + for (const requiredPath of requiredPaths) { + await assertPathExists( + join(packageRoot, requiredPath), + `${label} package path ${requiredPath}`, + ); + } +} + +function getRequiredPackPaths(rendererAssets) { + return [ + 'dist/cli/main.js', + 'dist/index.js', + 'dist/index.d.ts', + 'skills/agent-terminal/SKILL.md', + ...rendererAssets.map( + (assetPath) => `dist/renderer/ghosttyWeb/assets/${assetPath}`, + ), + ]; +} + +function assertPackedFiles(packMetadata, requiredPaths, label) { + assert( + Array.isArray(packMetadata.files), + `${label} pack metadata must include files`, + ); + const packedPaths = new Set( + packMetadata.files.map((entry) => { + assert( + typeof entry === 'object' && entry !== null, + `${label} pack entry must be an object`, + ); + const path = entry.path; + assert.equal(typeof path, 'string', 'pack entry path must be a string'); + return path; + }), + ); + + for (const requiredPath of requiredPaths) { + assert( + packedPaths.has(requiredPath), + `${label} pack is missing ${requiredPath}`, + ); + } +} + +async function resolveInstalledPackageRoot(prefix) { + const npmRootResult = runNpm(['root', '-g', '--prefix', prefix]); + const npmRoot = npmRootResult.stdout.trim(); + assert(npmRoot.length > 0, 'npm root output must not be empty'); + const packageRoot = join(npmRoot, packageName); + await assertPathExists(packageRoot, 'installed package root'); + return packageRoot; +} + +async function verifyInstalledCli(routeLabel, prefix) { + const packageRoot = await resolveInstalledPackageRoot(prefix); + const installedPackageJson = parseJsonOutput( + await readFile(join(packageRoot, 'package.json'), 'utf8'), + `${routeLabel} installed package.json`, + ); + assert( + typeof installedPackageJson === 'object' && installedPackageJson !== null, + `${routeLabel} installed package.json must be an object`, + ); + assert.equal( + installedPackageJson.version, + packageVersion, + `${routeLabel} installed package version mismatch`, + ); + + const rendererAssets = await listRelativeFiles( + join(projectRoot, 'src/renderer/ghosttyWeb/assets'), + ); + const requiredPaths = getRequiredPackPaths(rendererAssets); + await assertPackagePaths(packageRoot, requiredPaths, routeLabel); + + const binPath = join( + prefix, + 'bin', + process.platform === 'win32' ? `${binName}.cmd` : binName, + ); + await assertPathExists( + binPath, + `${routeLabel} installed binary`, + fsConstants.X_OK, + ); + + const versionResult = run(binPath, ['version', '--json']); + const versionEnvelope = parseJsonOutput( + versionResult.stdout, + `${routeLabel} version output`, + ); + assert( + typeof versionEnvelope === 'object' && versionEnvelope !== null, + `${routeLabel} version output must be an object`, + ); + assert.equal(versionEnvelope.ok, true, `${routeLabel} version must succeed`); + assert.equal( + versionEnvelope.command, + 'version', + `${routeLabel} version command mismatch`, + ); + assert( + typeof versionEnvelope.result === 'object' && + versionEnvelope.result !== null, + `${routeLabel} version result must be an object`, + ); + assert.equal( + versionEnvelope.result.cliVersion, + packageVersion, + `${routeLabel} CLI version mismatch`, + ); + + const home = await mkdtemp( + join(tempRoot, `${routeLabel.toLowerCase()}-home-`), + ); + const doctorResult = run(binPath, ['--home', home, 'doctor', '--json']); + const doctorEnvelope = parseJsonOutput( + doctorResult.stdout, + `${routeLabel} doctor output`, + ); + assert( + typeof doctorEnvelope === 'object' && doctorEnvelope !== null, + `${routeLabel} doctor output must be an object`, + ); + assert.equal( + doctorEnvelope.ok, + true, + `${routeLabel} doctor must emit success envelope`, + ); + assert.equal( + doctorEnvelope.command, + 'doctor', + `${routeLabel} doctor command mismatch`, + ); + assert( + typeof doctorEnvelope.result === 'object' && doctorEnvelope.result !== null, + `${routeLabel} doctor result must be an object`, + ); + assert.equal( + doctorEnvelope.result.ok, + true, + `${routeLabel} doctor result must pass`, + ); +} + +function shouldCopyPath(sourcePath) { + const relativePath = relative(projectRoot, sourcePath); + if (relativePath.length === 0) { + return true; + } + + const normalizedRelativePath = relativePath.replaceAll('\\', '/'); + if ( + normalizedRelativePath === 'dogfood/install-flows' || + normalizedRelativePath.startsWith('dogfood/install-flows/') + ) { + return false; + } + + const pathParts = relativePath.split(/[/\\]+/); + const fileName = basename(sourcePath); + if ( + pathParts.includes('.git') || + pathParts.includes('node_modules') || + pathParts.includes('dist') || + pathParts.includes('coverage') + ) { + return false; + } + + return !( + fileName.endsWith('.tsbuildinfo') || + fileName.endsWith('.tgz') || + fileName === '.DS_Store' + ); +} + +async function createGitInstallSource() { + const gitSourceRoot = join(tempRoot, 'git-source'); + await cp(projectRoot, gitSourceRoot, { + recursive: true, + filter: shouldCopyPath, + }); + + run('git', ['init', '--quiet'], { cwd: gitSourceRoot }); + run('git', ['config', 'user.email', 'agent-terminal@example.invalid'], { + cwd: gitSourceRoot, + }); + run('git', ['config', 'user.name', 'agent-terminal smoke'], { + cwd: gitSourceRoot, + }); + run('git', ['add', '--all'], { cwd: gitSourceRoot }); + run('git', ['commit', '--quiet', '--message', 'package smoke'], { + cwd: gitSourceRoot, + }); + + const revisionResult = run('git', ['rev-parse', 'HEAD'], { + cwd: gitSourceRoot, + }); + const revision = revisionResult.stdout.trim(); + assert(revision.length > 0, 'git source revision must not be empty'); + + return { + gitSourceRoot, + gitUrl: `git+${pathToFileURL(gitSourceRoot).href}#${revision}`, + }; +} + +try { + const rendererAssets = await listRelativeFiles( + join(projectRoot, 'src/renderer/ghosttyWeb/assets'), + ); + const requiredPaths = getRequiredPackPaths(rendererAssets); + + if (!skipBuild) { + logStep('Building package contents for tarball smoke...'); + runNpm(['run', 'build']); + } + + logStep('Packing private tarball from built workspace...'); + const tarballDirectory = join(tempRoot, 'tarball'); + const tarballInstallPrefix = join(tempRoot, 'tarball-prefix'); + await mkdir(tarballDirectory, { recursive: true }); + const packResult = runNpm([ + 'pack', + '--json', + '--ignore-scripts', + '--pack-destination', + tarballDirectory, + ]); + const packMetadata = parseJsonOutput(packResult.stdout, 'npm pack output'); + assert(Array.isArray(packMetadata), 'npm pack output must be an array'); + assert.equal( + packMetadata.length, + 1, + 'npm pack output must contain one entry', + ); + const [packEntry] = packMetadata; + assert( + typeof packEntry === 'object' && packEntry !== null, + 'npm pack entry must be an object', + ); + assert.equal(packEntry.name, packageName, 'packed package name mismatch'); + assert.equal( + packEntry.version, + packageVersion, + 'packed package version mismatch', + ); + assertPackedFiles(packEntry, requiredPaths, 'tarball'); + + const tarballFilename = packEntry.filename; + assert.equal( + typeof tarballFilename, + 'string', + 'packed tarball filename missing', + ); + const tarballPath = join(tarballDirectory, tarballFilename); + const tarballStats = await stat(tarballPath); + assert(tarballStats.size > 0, 'packed tarball must not be empty'); + + logStep('Installing built tarball into isolated prefix...'); + runNpm(['install', '-g', '--prefix', tarballInstallPrefix, tarballPath]); + await verifyInstalledCli('Tarball', tarballInstallPrefix); + + logStep( + 'Preparing clean git source to exercise npm prepare for git installs...', + ); + const gitInstallPrefix = join(tempRoot, 'git-prefix'); + const { gitUrl } = await createGitInstallSource(); + + logStep('Installing from git dependency URL into isolated prefix...'); + const gitInstallResult = runNpm( + ['install', '-g', '--prefix', gitInstallPrefix, gitUrl], + { allowFailure: true }, + ); + + if (gitInstallResult.status === 0) { + await verifyInstalledCli('Git', gitInstallPrefix); + logStep('Git dependency install route succeeded.'); + } else { + assert( + isKnownGitInstallCaveat(gitInstallResult), + [ + 'git dependency install failed in an unexpected way', + gitInstallResult.stdout.length === 0 + ? '' + : `stdout:\n${gitInstallResult.stdout}`, + gitInstallResult.stderr.length === 0 + ? '' + : `stderr:\n${gitInstallResult.stderr}`, + ] + .filter((line) => line.length > 0) + .join('\n\n'), + ); + logStep( + 'Git dependency install matched the known caveat path; tarball fallback remains the guaranteed route.', + ); + } + + logStep( + 'Packaging smoke passed: tarball route succeeded, and the current git-install behavior was validated.', + ); +} finally { + await rm(tempRoot, { recursive: true, force: true }); +}