From 28f4c9267799394af82c6680d9aab652708e925a Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Mon, 13 Jul 2026 13:12:20 +0700 Subject: [PATCH 1/8] chore(porch): bugfix-1158 init bugfix --- .../status.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml diff --git a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml new file mode 100644 index 000000000..2f2e9dd7d --- /dev/null +++ b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml @@ -0,0 +1,14 @@ +id: bugfix-1158 +title: vscode-strip-dev-server-termin +protocol: bugfix +phase: investigate +plan_phases: [] +current_plan_phase: null +gates: + pr: + status: pending +iteration: 1 +build_complete: false +history: [] +started_at: '2026-07-13T06:12:19.993Z' +updated_at: '2026-07-13T06:12:19.994Z' From f44aa6d93a033765a13dab3965e572fdadab14ba Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Mon, 13 Jul 2026 13:17:03 +0700 Subject: [PATCH 2/8] chore(porch): bugfix-1158 fix phase-transition --- .../bugfix-1158-vscode-strip-dev-server-termin/status.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml index 2f2e9dd7d..e1a29e366 100644 --- a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml +++ b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml @@ -1,7 +1,7 @@ id: bugfix-1158 title: vscode-strip-dev-server-termin protocol: bugfix -phase: investigate +phase: fix plan_phases: [] current_plan_phase: null gates: @@ -11,4 +11,4 @@ iteration: 1 build_complete: false history: [] started_at: '2026-07-13T06:12:19.993Z' -updated_at: '2026-07-13T06:12:19.994Z' +updated_at: '2026-07-13T06:17:03.100Z' From f6acd5c393c1c53cc2db98b3ee16063887bb93b2 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Mon, 13 Jul 2026 13:30:43 +0700 Subject: [PATCH 3/8] [Bugfix #1158] Fix: strip "dev server" terminology from VS Code surfaces Close the naming gap so config -> CLI -> VS Code all read "dev". The config field (worktree.devCommand) and CLI (afx dev) were already neutral; only the VS Code titles, several command ids, one context key, one view id, five source file names, and doc prose still carried the web-centric "dev server." - package.json: strip "Server" from 6 command titles; codev.devServer.* -> codev.dev.* command ids; context key codev.devServerRunning -> codev.devRunning; view id codev.devServer -> codev.dev. - extension.ts / views / commands: rename internal identifiers (stopDevServer -> stopDev, DevServerTreeProvider -> DevTreeProvider, etc.), the auto view-focus command codev.devServer.focus -> codev.dev.focus, and neutralize user-facing strings / comments. - Rename source files: dev-server-actions.ts -> dev-actions.ts, views/dev-server.ts -> dev.ts, views/dev-server-format.ts -> dev-format.ts (+ the two test files). - Docs: sharpen AGENTS.md / CLAUDE.md "Runnable Worktrees" prose so non-web users (cargo run, expo start, test watchers, build scripts) don't self-exclude; update PIR protocol/prompt command names; fix arch.md's now-stale #921 identifiers. - Left historical records unchanged (plans 921/1104/975, review 921, projectlist). BREAKING (per-user, minor): old keybindings on codev.devServer.* silently no-op; the codev.dev view id invalidates any user override of the old view's visibility. Grep of packages/vscode for devServer / "Dev Server" / dev-server = 0 hits. --- AGENTS.md | 20 ++-- CLAUDE.md | 20 ++-- .../protocols/pir/prompts/implement.md | 2 +- .../protocols/pir/prompts/review.md | 2 +- codev-skeleton/protocols/pir/protocol.md | 4 +- codev/protocols/pir/prompts/implement.md | 2 +- codev/protocols/pir/prompts/review.md | 2 +- codev/protocols/pir/protocol.md | 4 +- codev/resources/arch.md | 4 +- codev/state/bugfix-1158_thread.md | 70 +++++++++++ packages/vscode/package.json | 58 ++++----- .../__tests__/contributes-dev-server.test.ts | 81 ------------- .../src/__tests__/contributes-dev.test.ts | 113 ++++++++++++++++++ .../src/__tests__/contributes-panel.test.ts | 4 +- ...rver-format.test.ts => dev-format.test.ts} | 2 +- .../has-runnable-dev-command.test.ts | 2 +- .../src/__tests__/menu-when-clauses.test.ts | 6 +- .../src/__tests__/terminal-manager.test.ts | 2 +- packages/vscode/src/command-relay.ts | 2 +- .../{dev-server-actions.ts => dev-actions.ts} | 8 +- packages/vscode/src/commands/dev-shared.ts | 4 +- .../vscode/src/commands/run-workspace-dev.ts | 2 +- .../vscode/src/commands/run-worktree-dev.ts | 2 +- .../vscode/src/commands/stop-worktree-dev.ts | 6 +- packages/vscode/src/extension.ts | 44 +++---- packages/vscode/src/load-worktree-config.ts | 2 +- packages/vscode/src/terminal-manager.ts | 10 +- .../{dev-server-format.ts => dev-format.ts} | 0 .../src/views/{dev-server.ts => dev.ts} | 6 +- packages/vscode/src/views/workspace.ts | 20 ++-- 30 files changed, 303 insertions(+), 201 deletions(-) create mode 100644 codev/state/bugfix-1158_thread.md delete mode 100644 packages/vscode/src/__tests__/contributes-dev-server.test.ts create mode 100644 packages/vscode/src/__tests__/contributes-dev.test.ts rename packages/vscode/src/__tests__/{dev-server-format.test.ts => dev-format.test.ts} (98%) rename packages/vscode/src/commands/{dev-server-actions.ts => dev-actions.ts} (94%) rename packages/vscode/src/views/{dev-server-format.ts => dev-format.ts} (100%) rename packages/vscode/src/views/{dev-server.ts => dev.ts} (97%) diff --git a/AGENTS.md b/AGENTS.md index c48b754f4..f59dcbecf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -376,7 +376,7 @@ Codev provides five CLI tools. For complete reference documentation, see: ## Runnable Worktrees -When configured, each builder worktree (`.builders//`) becomes runnable — reviewers can spin up a dev server against the builder's branch without `cd`'ing, manually installing, or finding the right command. Opt-in via `.codev/config.json`; unconfigured repos see zero behavior change. +When configured, each builder worktree (`.builders//`) becomes runnable — reviewers can run whatever your dev command starts against the builder's branch — a dev server, `cargo run`, `expo start`, a test watcher, a build script, whatever iterates on your project — without `cd`'ing, manually installing, or finding the right command. Opt-in via `.codev/config.json`; unconfigured repos see zero behavior change. ### Config: the `worktree` block @@ -392,15 +392,15 @@ When configured, each builder worktree (`.builders//`) becomes runnable — - `symlinks`: globs resolve from the workspace root; matches symlink into the worktree at the same relative path. Root `.env` and `.codev/config.json` are *always* symlinked regardless. **Symlinks, not copies** — edits to main's env files reflect instantly in any running dev session. A directory match is silently skipped (so a glob can't mask the worktree's own source) **unless** the entry ends with a trailing slash: `".local-user-data/"` is treated as a literal path and symlinks the directory whole (shared with the parent, not branch-isolated; a dangling link is fine if the source doesn't exist yet). - `postSpawn`: each command runs sequentially with `cwd` = worktree path. Non-zero exit aborts the spawn loud (half-built worktree stays for inspection). -- `devCommand`: the foreground command that starts your dev server. Required for `afx dev` to work. +- `devCommand`: the foreground command that starts your dev process (a server, a watcher, `cargo run`, `expo start`, a build script — whatever iterates on your project). Required for `afx dev` to work. **Codev does not auto-detect your stack.** Pick the recipe below that matches your toolchain. ### CLI ```bash -afx dev # start the dev server in 's worktree -afx dev main # start the dev server in the MAIN workspace (Codev-managed) +afx dev # start dev in 's worktree +afx dev main # start dev in the MAIN workspace (Codev-managed) afx dev --stop # stop the currently running dev PTY (builder or main) ``` @@ -416,19 +416,19 @@ The same actions are available via right-click on any builder row in the Codev s - **Codev: Open Worktree Folder** — opens `.builders//` in the OS file manager (Finder on macOS, Explorer on Windows, xdg-open on Linux). - **Codev: Run Worktree Setup** — applies the configured `worktree.symlinks` and runs the `worktree.postSpawn` commands against the existing worktree (mirrors what spawn does, minus the git steps). Idempotent: existing symlinks are skipped, missing ones added. Useful when the lockfile changed (reinstall deps), `symlinks` or `postSpawn` was extended after the builder spawned, a symlink was accidentally deleted, or the original setup aborted mid-run. Opens a fresh VSCode terminal so install output streams live. Available via CLI too: `afx setup `. - **Codev: View Diff** — opens a single unified diff editor for `main...HEAD` of that builder's worktree, with a file-list pane on the left (matches VSCode's built-in Source Control "Working Tree" view). Status icons indicate added / modified / deleted. Empty diff → friendly toast. -- **Codev: Run Dev Server** — reads `worktree.devCommand` from `.codev/config.json`, asks Tower to spawn a dev PTY in the builder's worktree, and opens it as a VSCode terminal tab named `Codev: (dev)`. If another builder's dev is already running, you get a modal asking whether to swap. -- **Codev: Stop Dev Server** — kills the running dev PTY and closes its tab. +- **Codev: Run Dev** — reads `worktree.devCommand` from `.codev/config.json`, asks Tower to spawn a dev PTY in the builder's worktree, and opens it as a VSCode terminal tab named `Codev: (dev)`. If another builder's dev is already running, you get a modal asking whether to swap. +- **Codev: Stop Dev** — kills the running dev PTY and closes its tab. -The Codev sidebar's **Workspace** view also carries a dev server for *whatever folder this VSCode window is rooted at* (it is not "main"-specific): +The Codev sidebar's **Workspace** view also carries a dev control for *whatever folder this VSCode window is rooted at* (it is not "main"-specific): -- **Start Dev Server** — runs `worktree.devCommand` for the current workspace. Target is resolved from the open folder: the main checkout → `main`; a `.builders//` worktree opened as its own window (e.g. via *Open Worktree as Workspace*) → that builder. Same single-slot swap model as builder dev (prompts if another dev is running). The row tooltip names the resolved target. -- **Stop Dev Server** — stops this workspace's dev server; the row appears only while it is running. Scoped to the resolved target — it does not touch other devs. +- **Start Dev** — runs `worktree.devCommand` for the current workspace. Target is resolved from the open folder: the main checkout → `main`; a `.builders//` worktree opened as its own window (e.g. via *Open Worktree as Workspace*) → that builder. Same single-slot swap model as builder dev (prompts if another dev is running). The row tooltip names the resolved target. +- **Stop Dev** — stops this workspace's dev; the row appears only while it is running. Scoped to the resolved target — it does not touch other devs. The three commands are also available from the command palette (Cmd+Shift+P). No default keybindings; bind via `keybindings.json` if you use them often. ### URLs are load-bearing -The dev PTY uses **the same ports and URLs as main** intentionally. OAuth callbacks, CORS allowlists, cookie scoping, CSP `connect-src`, webhook URLs are all keyed off origin — running the worktree on a different port would break them. Consequence: stop main's `pnpm dev` before `afx dev`. If you don't, the spawned dev fails at bind time with its own `EADDRINUSE`. Prefer `afx dev main` (or the Workspace view's *Start Dev Server* row) over a hand-run `pnpm dev` so Codev owns the PTY and swap-detection can stop it for you automatically. +The dev PTY uses **the same ports and URLs as main** intentionally. OAuth callbacks, CORS allowlists, cookie scoping, CSP `connect-src`, webhook URLs are all keyed off origin — running the worktree on a different port would break them. Consequence: stop main's `pnpm dev` before `afx dev`. If you don't, the spawned dev fails at bind time with its own `EADDRINUSE`. Prefer `afx dev main` (or the Workspace view's *Start Dev* row) over a hand-run `pnpm dev` so Codev owns the PTY and swap-detection can stop it for you automatically. ### Cleanup semantics diff --git a/CLAUDE.md b/CLAUDE.md index c48b754f4..f59dcbecf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -376,7 +376,7 @@ Codev provides five CLI tools. For complete reference documentation, see: ## Runnable Worktrees -When configured, each builder worktree (`.builders//`) becomes runnable — reviewers can spin up a dev server against the builder's branch without `cd`'ing, manually installing, or finding the right command. Opt-in via `.codev/config.json`; unconfigured repos see zero behavior change. +When configured, each builder worktree (`.builders//`) becomes runnable — reviewers can run whatever your dev command starts against the builder's branch — a dev server, `cargo run`, `expo start`, a test watcher, a build script, whatever iterates on your project — without `cd`'ing, manually installing, or finding the right command. Opt-in via `.codev/config.json`; unconfigured repos see zero behavior change. ### Config: the `worktree` block @@ -392,15 +392,15 @@ When configured, each builder worktree (`.builders//`) becomes runnable — - `symlinks`: globs resolve from the workspace root; matches symlink into the worktree at the same relative path. Root `.env` and `.codev/config.json` are *always* symlinked regardless. **Symlinks, not copies** — edits to main's env files reflect instantly in any running dev session. A directory match is silently skipped (so a glob can't mask the worktree's own source) **unless** the entry ends with a trailing slash: `".local-user-data/"` is treated as a literal path and symlinks the directory whole (shared with the parent, not branch-isolated; a dangling link is fine if the source doesn't exist yet). - `postSpawn`: each command runs sequentially with `cwd` = worktree path. Non-zero exit aborts the spawn loud (half-built worktree stays for inspection). -- `devCommand`: the foreground command that starts your dev server. Required for `afx dev` to work. +- `devCommand`: the foreground command that starts your dev process (a server, a watcher, `cargo run`, `expo start`, a build script — whatever iterates on your project). Required for `afx dev` to work. **Codev does not auto-detect your stack.** Pick the recipe below that matches your toolchain. ### CLI ```bash -afx dev # start the dev server in 's worktree -afx dev main # start the dev server in the MAIN workspace (Codev-managed) +afx dev # start dev in 's worktree +afx dev main # start dev in the MAIN workspace (Codev-managed) afx dev --stop # stop the currently running dev PTY (builder or main) ``` @@ -416,19 +416,19 @@ The same actions are available via right-click on any builder row in the Codev s - **Codev: Open Worktree Folder** — opens `.builders//` in the OS file manager (Finder on macOS, Explorer on Windows, xdg-open on Linux). - **Codev: Run Worktree Setup** — applies the configured `worktree.symlinks` and runs the `worktree.postSpawn` commands against the existing worktree (mirrors what spawn does, minus the git steps). Idempotent: existing symlinks are skipped, missing ones added. Useful when the lockfile changed (reinstall deps), `symlinks` or `postSpawn` was extended after the builder spawned, a symlink was accidentally deleted, or the original setup aborted mid-run. Opens a fresh VSCode terminal so install output streams live. Available via CLI too: `afx setup `. - **Codev: View Diff** — opens a single unified diff editor for `main...HEAD` of that builder's worktree, with a file-list pane on the left (matches VSCode's built-in Source Control "Working Tree" view). Status icons indicate added / modified / deleted. Empty diff → friendly toast. -- **Codev: Run Dev Server** — reads `worktree.devCommand` from `.codev/config.json`, asks Tower to spawn a dev PTY in the builder's worktree, and opens it as a VSCode terminal tab named `Codev: (dev)`. If another builder's dev is already running, you get a modal asking whether to swap. -- **Codev: Stop Dev Server** — kills the running dev PTY and closes its tab. +- **Codev: Run Dev** — reads `worktree.devCommand` from `.codev/config.json`, asks Tower to spawn a dev PTY in the builder's worktree, and opens it as a VSCode terminal tab named `Codev: (dev)`. If another builder's dev is already running, you get a modal asking whether to swap. +- **Codev: Stop Dev** — kills the running dev PTY and closes its tab. -The Codev sidebar's **Workspace** view also carries a dev server for *whatever folder this VSCode window is rooted at* (it is not "main"-specific): +The Codev sidebar's **Workspace** view also carries a dev control for *whatever folder this VSCode window is rooted at* (it is not "main"-specific): -- **Start Dev Server** — runs `worktree.devCommand` for the current workspace. Target is resolved from the open folder: the main checkout → `main`; a `.builders//` worktree opened as its own window (e.g. via *Open Worktree as Workspace*) → that builder. Same single-slot swap model as builder dev (prompts if another dev is running). The row tooltip names the resolved target. -- **Stop Dev Server** — stops this workspace's dev server; the row appears only while it is running. Scoped to the resolved target — it does not touch other devs. +- **Start Dev** — runs `worktree.devCommand` for the current workspace. Target is resolved from the open folder: the main checkout → `main`; a `.builders//` worktree opened as its own window (e.g. via *Open Worktree as Workspace*) → that builder. Same single-slot swap model as builder dev (prompts if another dev is running). The row tooltip names the resolved target. +- **Stop Dev** — stops this workspace's dev; the row appears only while it is running. Scoped to the resolved target — it does not touch other devs. The three commands are also available from the command palette (Cmd+Shift+P). No default keybindings; bind via `keybindings.json` if you use them often. ### URLs are load-bearing -The dev PTY uses **the same ports and URLs as main** intentionally. OAuth callbacks, CORS allowlists, cookie scoping, CSP `connect-src`, webhook URLs are all keyed off origin — running the worktree on a different port would break them. Consequence: stop main's `pnpm dev` before `afx dev`. If you don't, the spawned dev fails at bind time with its own `EADDRINUSE`. Prefer `afx dev main` (or the Workspace view's *Start Dev Server* row) over a hand-run `pnpm dev` so Codev owns the PTY and swap-detection can stop it for you automatically. +The dev PTY uses **the same ports and URLs as main** intentionally. OAuth callbacks, CORS allowlists, cookie scoping, CSP `connect-src`, webhook URLs are all keyed off origin — running the worktree on a different port would break them. Consequence: stop main's `pnpm dev` before `afx dev`. If you don't, the spawned dev fails at bind time with its own `EADDRINUSE`. Prefer `afx dev main` (or the Workspace view's *Start Dev* row) over a hand-run `pnpm dev` so Codev owns the PTY and swap-detection can stop it for you automatically. ### Cleanup semantics diff --git a/codev-skeleton/protocols/pir/prompts/implement.md b/codev-skeleton/protocols/pir/prompts/implement.md index 90e74423d..9d7f88a8c 100644 --- a/codev-skeleton/protocols/pir/prompts/implement.md +++ b/codev-skeleton/protocols/pir/prompts/implement.md @@ -121,7 +121,7 @@ When the gate goes pending, output a short prose summary in the pane to orient t > > **Things to look at**: tricky spots, platform-specific behavior, anything you want the reviewer to focus on. > -> **How to test locally**: VSCode → right-click builder → **Run Dev Server**, or `afx dev pir-{{project_id}}`. View diff via VSCode → **View Diff** (auto-detects the repo's default branch). +> **How to test locally**: VSCode → right-click builder → **Run Dev**, or `afx dev pir-{{project_id}}`. View diff via VSCode → **View Diff** (auto-detects the repo's default branch). > > Ready for review — type feedback here, or approve with `porch approve {{project_id}} dev-approval --a-human-explicitly-approved-this` (Cmd+K G in VSCode). diff --git a/codev-skeleton/protocols/pir/prompts/review.md b/codev-skeleton/protocols/pir/prompts/review.md index c7ada1e68..952f19c29 100644 --- a/codev-skeleton/protocols/pir/prompts/review.md +++ b/codev-skeleton/protocols/pir/prompts/review.md @@ -75,7 +75,7 @@ Tricky spots the PR reviewer should focus on. Honest — if a section was hard t For reviewers pulling the branch: - **View diff**: VSCode sidebar → right-click builder pir-{{project_id}} → **Review Diff** (auto-detects the repo's default branch) -- **Run dev server**: VSCode sidebar → **Run Dev Server**, or `afx dev pir-{{project_id}}` +- **Run dev**: VSCode sidebar → **Run Dev**, or `afx dev pir-{{project_id}}` - **What to verify**: ## Flaky Tests (if any) diff --git a/codev-skeleton/protocols/pir/protocol.md b/codev-skeleton/protocols/pir/protocol.md index 9108102a6..0e68f92f8 100644 --- a/codev-skeleton/protocols/pir/protocol.md +++ b/codev-skeleton/protocols/pir/protocol.md @@ -83,10 +83,10 @@ The builder: **The reviewer's killer move**: run the worktree locally. -- VSCode: right-click the builder in the Codev sidebar → **Run Dev Server** (spawns `afx dev ` via Tower) +- VSCode: right-click the builder in the Codev sidebar → **Run Dev** (spawns `afx dev ` via Tower) - CLI: `afx dev ` -The dev server uses **the same ports and URLs as main** intentionally (OAuth callbacks, CORS, cookie scoping all depend on consistent origins). Only one dev env runs at a time; stop main's `pnpm dev` before starting the worktree's, or use VSCode's **Stop Dev Server** to swap. +The dev process uses **the same ports and URLs as main** intentionally (OAuth callbacks, CORS, cookie scoping all depend on consistent origins). Only one dev env runs at a time; stop main's `pnpm dev` before starting the worktree's, or use VSCode's **Stop Dev** to swap. Reviewer tests the change on real devices / browsers / simulators. When satisfied, approves via Cmd+K G or: diff --git a/codev/protocols/pir/prompts/implement.md b/codev/protocols/pir/prompts/implement.md index 90e74423d..9d7f88a8c 100644 --- a/codev/protocols/pir/prompts/implement.md +++ b/codev/protocols/pir/prompts/implement.md @@ -121,7 +121,7 @@ When the gate goes pending, output a short prose summary in the pane to orient t > > **Things to look at**: tricky spots, platform-specific behavior, anything you want the reviewer to focus on. > -> **How to test locally**: VSCode → right-click builder → **Run Dev Server**, or `afx dev pir-{{project_id}}`. View diff via VSCode → **View Diff** (auto-detects the repo's default branch). +> **How to test locally**: VSCode → right-click builder → **Run Dev**, or `afx dev pir-{{project_id}}`. View diff via VSCode → **View Diff** (auto-detects the repo's default branch). > > Ready for review — type feedback here, or approve with `porch approve {{project_id}} dev-approval --a-human-explicitly-approved-this` (Cmd+K G in VSCode). diff --git a/codev/protocols/pir/prompts/review.md b/codev/protocols/pir/prompts/review.md index c7ada1e68..952f19c29 100644 --- a/codev/protocols/pir/prompts/review.md +++ b/codev/protocols/pir/prompts/review.md @@ -75,7 +75,7 @@ Tricky spots the PR reviewer should focus on. Honest — if a section was hard t For reviewers pulling the branch: - **View diff**: VSCode sidebar → right-click builder pir-{{project_id}} → **Review Diff** (auto-detects the repo's default branch) -- **Run dev server**: VSCode sidebar → **Run Dev Server**, or `afx dev pir-{{project_id}}` +- **Run dev**: VSCode sidebar → **Run Dev**, or `afx dev pir-{{project_id}}` - **What to verify**: ## Flaky Tests (if any) diff --git a/codev/protocols/pir/protocol.md b/codev/protocols/pir/protocol.md index 9108102a6..0e68f92f8 100644 --- a/codev/protocols/pir/protocol.md +++ b/codev/protocols/pir/protocol.md @@ -83,10 +83,10 @@ The builder: **The reviewer's killer move**: run the worktree locally. -- VSCode: right-click the builder in the Codev sidebar → **Run Dev Server** (spawns `afx dev ` via Tower) +- VSCode: right-click the builder in the Codev sidebar → **Run Dev** (spawns `afx dev ` via Tower) - CLI: `afx dev ` -The dev server uses **the same ports and URLs as main** intentionally (OAuth callbacks, CORS, cookie scoping all depend on consistent origins). Only one dev env runs at a time; stop main's `pnpm dev` before starting the worktree's, or use VSCode's **Stop Dev Server** to swap. +The dev process uses **the same ports and URLs as main** intentionally (OAuth callbacks, CORS, cookie scoping all depend on consistent origins). Only one dev env runs at a time; stop main's `pnpm dev` before starting the worktree's, or use VSCode's **Stop Dev** to swap. Reviewer tests the change on real devices / browsers / simulators. When satisfied, approves via Cmd+K G or: diff --git a/codev/resources/arch.md b/codev/resources/arch.md index 9f10ceaa6..6ba08de1e 100644 --- a/codev/resources/arch.md +++ b/codev/resources/arch.md @@ -1112,8 +1112,8 @@ The VS Code extension (`packages/vscode`) is a thin client over Tower's existing - **Subpath exports**: `codev-core` uses subpath exports (`./tower-client`, `./escape-buffer`, etc.) to prevent Node builtins from leaking into the dashboard's Vite build. - **Injectable auth**: `TowerClient` accepts a `getAuthKey` callback. CLI uses `ensureLocalKey()` (creates key if missing). Extension uses `readLocalKey()` + `SecretStorage` (never creates keys). - **Editor-tab webviews (#920)**: Richer-than-TreeView surfaces use `vscode.window.createWebviewPanel` (editor area), not a sidebar `WebviewView`. Pattern: the panel is a thin view that posts debounced criteria to the extension host; **filtering/sorting runs host-side** in vscode-free pure helpers (`views/backlog-filter.ts`, vitest-tested) so logic stays testable and sensitive data (e.g. issue bodies) never crosses into the webview — only display rows do. HTML/CSS/JS live in a sibling `*.template.ts` (no esbuild asset-copy step); theming is **CSS variables only** (`--vscode-*`) so dark/light/high-contrast render natively; CSP is nonce'd. First instance: the "Search Backlog" panel (`webviews/backlog-search-panel.ts`), fed by the dedicated `issue-search` forge concept → `GET /api/issue-search` (kept separate from `issue-list` so `/api/overview` stays body-free). -- **Panel view container (#812)**: The extension contributes view containers to **two** locations — `activitybar.codev` (the 7-section sidebar) and `panel.codevPanel` (bottom panel, wide-short geometry). The panel exists as scaffolding for views whose shape suits a wide layout (timelines, rosters, tables); migrations are tracked separately (#813/#814/#815). Panel views are plain `TreeDataProvider`s, identical in kind to sidebar providers — VS Code lets the same view types live in either location. A `codev.panelContainerEmpty` context key gates a placeholder view that hides once real views register — **#921's `codev.devServer` is the first such view, so the panel now ships non-empty** (the key is seeded `false`). VS Code gives no control over panel-tab *position* (it lands last, in the `…` overflow), so the extension does a one-time, globalState-guarded reveal (`workbench.view.extension.codevPanel`) on first activation for discoverability. -- **Codev Dev surface (#921)**: The single `afx dev` PTY gets two complementary surfaces, both driven off the one `TerminalManager.onDidChangeDevTerminals` event (single source of truth, so chip and tab never drift on start/stop/swap): a `codev.devServer` panel `TreeDataProvider` (first real `codevPanel` tenant — status header of target / live-ticking uptime / best-effort port, plus title-bar Stop / Restart / Switch-Target / Show-Hide-sidebar actions gated by a `codev.devServerRunning` key) and an always-visible **status-bar chip** (`StatusBarItem`, left, priority 99) shown only while a dev runs, clicking through to the tab. The native `Codev: (dev)` terminal stays as the output surface (coexist) — the new tab is a status/control surface, not an output mirror, so there is no second PTY/xterm re-plumbing. Uptime needs a start time `listDevTerminals()` doesn't carry, so `TerminalManager` keeps a `builderId → startedAt` map. Pure formatters (`views/dev-server-format.ts`: uptime, port-from-config) are vitest-tested. +- **Panel view container (#812)**: The extension contributes view containers to **two** locations — `activitybar.codev` (the 7-section sidebar) and `panel.codevPanel` (bottom panel, wide-short geometry). The panel exists as scaffolding for views whose shape suits a wide layout (timelines, rosters, tables); migrations are tracked separately (#813/#814/#815). Panel views are plain `TreeDataProvider`s, identical in kind to sidebar providers — VS Code lets the same view types live in either location. A `codev.panelContainerEmpty` context key gates a placeholder view that hides once real views register — **#921's `codev.dev` is the first such view, so the panel now ships non-empty** (the key is seeded `false`). VS Code gives no control over panel-tab *position* (it lands last, in the `…` overflow), so the extension does a one-time, globalState-guarded reveal (`workbench.view.extension.codevPanel`) on first activation for discoverability. +- **Codev Dev surface (#921)**: The single `afx dev` PTY gets two complementary surfaces, both driven off the one `TerminalManager.onDidChangeDevTerminals` event (single source of truth, so chip and tab never drift on start/stop/swap): a `codev.dev` panel `TreeDataProvider` (first real `codevPanel` tenant — status header of target / live-ticking uptime / best-effort port, plus title-bar Stop / Restart / Switch-Target / Show-Hide-sidebar actions gated by a `codev.devRunning` key) and an always-visible **status-bar chip** (`StatusBarItem`, left, priority 99) shown only while a dev runs, clicking through to the tab. The native `Codev: (dev)` terminal stays as the output surface (coexist) — the new tab is a status/control surface, not an output mirror, so there is no second PTY/xterm re-plumbing. Uptime needs a start time `listDevTerminals()` doesn't carry, so `TerminalManager` keeps a `builderId → startedAt` map. Pure formatters (`views/dev-format.ts`: uptime, port-from-config) are vitest-tested. - **Startup CLI preflight (#791)**: On `activate()` the extension verifies the `codev` CLI is installed and at least its own `package.json` version (`codev --version`, resolved like `resolveAfxPath`, cached per session, 400ms-bounded, fire-and-forget so activation never blocks). Missing → `Get started with Codev` walkthrough; outdated → upgrade notification; either dismissed → CLI-dependent commands no-op with one "run setup" toast. Commands register through two helpers — `reg` (unguarded) and `regCli` (guarded) — so the registrar name *is* the guard policy (no separate list). Preflight also sets the `codev.cliReady` context key, which drives the walkthrough's Verify-step completion. Lives in `src/preflight/` (`preflight-core.ts` pure + unit-tested, `preflight.ts` vscode glue). - **Markdown Preview / artifact-canvas host integration (#859)**: The first integration of the shared `@cluesmith/codev-artifact-canvas` React surface into a host. A read-only `CustomTextEditor` (`codev.markdownPreview`, `priority: "option"` so it never replaces the default `.md` editor; selector scoped to `**/codev/{specs,plans,reviews}/**/*.md`) renders an artifact and lets a reviewer add comments by hovering a block and clicking `+`. It is the extension's **first bundled React webview**: a *second* esbuild entry (`esbuild.js`, browser/IIFE, bundles react/react-dom/the canvas + emits `markdown-preview.css`), type-checked by a dedicated `tsconfig.webview.json` (DOM libs) since the host `tsconfig.json` excludes the browser dir. Host↔webview bridge (`markdown-preview/preview-provider.ts`, HTML in a sibling `preview-template.ts` per #920; the two `postMessage` directions are a named protocol in `markdown-preview/messages.ts`, `HostToWebviewMessage` / `WebviewToHostMessage`, shared by both ends so they can't drift — #1107): the host posts **raw** document text + parsed markers; the webview mounts ``; the reviewer's `+`/Enter opens an **inline composer rendered in-flow below the block** (`overlays/CommentComposer.tsx`, portalled into a placeholder there — #1107 replaced the old center-top `showInputBox`); on submit `onAddComment(line, text)` → host `WorkspaceEdit` → the round-trip goes through the file text. (Host-side inbound `postMessage` data is untrusted, so the host still validates payload fields at runtime despite the named type.) **Cross-cutting invariants this established**: (1) the on-disk REVIEW-marker convention (``, a marker annotates the nearest non-marker line above it) lives in `@cluesmith/codev-core/review-markers` so every host (vscode now, dashboard later) writes/parses identical bytes — the editor Comments-API path (`comments/plan-review.ts`) shares it. (2) The canvas renderer runs markdown-it with **`html: true` + DOMPurify as the sole guard** (#1042 amends spec-945 D7: safe static HTML renders, scripts/handlers/`javascript:` stripped, document JS never executes) and **strips full-line HTML comments before block parsing** with a cleaned→original line map (#1036), so markers never render as text and never split a multi-line block while `data-line` stays accurate. - **Review-comment edit + preview-side delete — line+content identity (#1055)**: Extends the #859 review-marker surfaces to a full edit (both surfaces) + preview-delete tool **without any on-disk format change** (a stable-ID "format v2" was explicitly deferred to #1131). The identity a surface uses to locate one marker is its **physical file line** (`markerLine`), surfaced by `parseReviewMarkers` (the parser's own loop index) so a stack of comments on one block — which all share the annotated `line` — is individually addressable. `@cluesmith/codev-core/review-markers` owns the shared mechanics: `matchesExpectedMarker(lineText, author, bodyPrefix)` is an **optimistic-concurrency check** (author + whitespace-normalized body-prefix) and `rewriteReviewMarkerBody` re-serializes a marker's body while reading the author *off the existing line* (an edit can never reassign authorship). Every mutating write verifies first: the preview host (`markdown-preview/preview-provider.ts`, message types `editComment`/`deleteComment`) re-reads the line at `markerLine` and, on mismatch (the file changed between click and write), **refuses the write, re-pushes the document, and surfaces an info toast** rather than corrupting a different marker — the preview auto-refreshes anyway, so a race fails loudly. The canvas exposes optional `onEditComment`/`onDeleteComment` props (a read-only host renders plain cards) and per-card edit/delete affordances built as imperative DOM with inline stroke SVGs (host-agnostic — the webview can't assume VS Code's codicon font); a delegated body click routes them by `data-marker-line`. The editor Comments-API path (`comments/plan-review.ts`) gained an edit action (`ReviewComment` class carrying its parent thread; `startEditReviewComment` flips `mode` to `Editing` and **reassigns `thread.comments`** since VS Code only re-renders on reassignment; `saveEditReviewComment` rewrites via the same core helper). Multi-line bodies still collapse to one line at write time (`serializeReviewMarker` normalizes whitespace) — inherent to the single-line marker, deferred to #1131. diff --git a/codev/state/bugfix-1158_thread.md b/codev/state/bugfix-1158_thread.md new file mode 100644 index 000000000..f63763627 --- /dev/null +++ b/codev/state/bugfix-1158_thread.md @@ -0,0 +1,70 @@ +# bugfix-1158 — strip "dev server" terminology from VS Code surfaces + +## Issue +#1158 — VS Code runnable-worktrees surfaces still say "dev server" (web-centric). +Config (`worktree.devCommand`) and CLI (`afx dev`) are already neutral; close the gap +so config → CLI → VS Code all read "dev". + +## Investigate (phase 1) + +Root cause: purely a naming/terminology inconsistency. No behavior bug. Scope enumerated +in the issue. Confirmed BUGFIX-appropriate — mechanical rename + doc prose, no arch change. + +**Key constraint from verification criterion #6**: grep `packages/vscode/` for `devServer` +must yield ZERO hits post-fix. So internal identifiers must ALSO be renamed (not just +ids/titles/files): `stopDevServer`→`stopDev`, `restartDevServer`→`restartDev`, +`DevServerTreeProvider`→`DevTreeProvider`, `devServerProvider`→`devProvider`, +`devServerView`→`devView`, and the auto view-focus cmd `codev.devServer.focus`→`codev.dev.focus`. + +### Change map (packages/vscode) +- **package.json**: strip "Server" from 6 titles; `codev.devServer.*`→`codev.dev.*` (5 cmds + + palette + menus); ctx key `codev.devServerRunning`→`codev.devRunning`; view id + `codev.devServer`→`codev.dev`. +- **extension.ts**: imports, createTreeView view id, setContext key, cmd registrations, + focus cmd, internal var/class names. +- **File renames**: commands/dev-server-actions.ts→dev-actions.ts, views/dev-server.ts→dev.ts, + views/dev-server-format.ts→dev-format.ts, __tests__/contributes-dev-server.test.ts→ + contributes-dev.test.ts, __tests__/dev-server-format.test.ts→dev-format.test.ts. +- Comment/prose cleanups: terminal-manager.ts, command-relay.ts, load-worktree-config.ts, + dev-shared.ts, run/stop-*-dev.ts, views/workspace.ts, remaining test comments. + +### Docs (dual-tree mirror) +- AGENTS.md / CLAUDE.md (byte-identical) — "Runnable Worktrees" section, sharpen prose so + non-web users don't self-exclude (enumerate cargo run / expo start / test watcher / build). +- codev-skeleton/AGENTS.md + CLAUDE.md — same edits. +- codev-skeleton/protocols/pir/{protocol.md, prompts/implement.md, prompts/review.md} + codev/ mirrors. + +### CHANGELOG (per convention) +- packages/vscode/CHANGELOG.md + docs/releases/UNRELEASED.md — note the rename + keybinding + backward-compat break (old `codev.devServer.*` ids silently no-op post-upgrade). + +Est. well under 300 LOC of logic (mostly mechanical). Historical prose (projectlist, plan 975) +left UNCHANGED per §6. + +## Fix (phase 2) — DONE + +Applied the full rename. Result: grep `packages/vscode/` for `devServer` / `Dev Server` / +`dev-server` = ZERO hits (verification #6 ✓). Also updated `codev/resources/arch.md` (living +reference, not historical) whose #921 bullets named the now-dead `codev.devServer` view / +`codev.devServerRunning` key / `views/dev-server-format.ts`. Left historical records untouched: +`codev/plans/921`, `codev/plans/1104`, `codev/reviews/921`, `codev/state/pir-921_thread.md`, +projectlist, plan 975. + +**Regression guard**: the renamed `contributes-dev.test.ts` now asserts the new `codev.dev.*` +ids / `codev.devRunning` key / `codev.dev` view, PLUS a new `#1158` describe block that fails +if any command title contains "Server" or any id/view/when-clause contains "devServer". That +directly encodes verification criteria #1 and #6 as a permanent guard. + +**Backward-compat break (document in PR body)**: old keybindings on `codev.devServer.stop` / +`.restart` etc. silently no-op post-upgrade; view id `codev.dev` invalidates any user override +of the old `codev.devServer` view visibility. Both minor, per-user. Flagged to architect for +the VS Code CHANGELOG (updated separately on the changelog branch per repo convention). + +**Verification**: `pnpm test:unit` = 588 passed / 51 files; `pnpm compile` (check-types + lint ++ esbuild) = exit 0. Had to build workspace deps first (codev-core, codev-types, +artifact-canvas) — fresh worktree ships them unbuilt; those pre-existing module-resolution +errors were NOT from this change. + +**Scope note**: did NOT touch packages/vscode/CHANGELOG.md — vscode changelog is accumulated +on the dedicated changelog branch by the architect after cleanup (repo convention), not in +feature/bugfix PRs. Surfaced the migration note in the PR body + architect notification instead. diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 5fd689111..0c142d84b 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -250,46 +250,46 @@ }, { "command": "codev.runWorktreeDev", - "title": "Codev: Run Dev Server" + "title": "Codev: Run Dev" }, { "command": "codev.stopWorktreeDev", - "title": "Codev: Stop Dev Server" + "title": "Codev: Stop Dev" }, { "command": "codev.runWorkspaceDev", - "title": "Codev: Start Dev Server (this workspace)" + "title": "Codev: Start Dev (this workspace)" }, { "command": "codev.stopWorkspaceDev", - "title": "Codev: Stop Dev Server (this workspace)" + "title": "Codev: Stop Dev (this workspace)" }, { - "command": "codev.devServer.stop", - "title": "Stop Dev Server", + "command": "codev.dev.stop", + "title": "Stop Dev", "category": "Codev", "icon": "$(debug-stop)" }, { - "command": "codev.devServer.restart", - "title": "Restart Dev Server", + "command": "codev.dev.restart", + "title": "Restart Dev", "category": "Codev", "icon": "$(debug-restart)" }, { - "command": "codev.devServer.switchTarget", + "command": "codev.dev.switchTarget", "title": "Switch Target", "category": "Codev", "icon": "$(arrow-swap)" }, { - "command": "codev.devServer.showSidebar", + "command": "codev.dev.showSidebar", "title": "Show Codev Sidebar", "category": "Codev", "icon": "$(eye)" }, { - "command": "codev.devServer.hideSidebar", + "command": "codev.dev.hideSidebar", "title": "Hide Codev Sidebar", "category": "Codev", "icon": "$(eye-closed)" @@ -484,23 +484,23 @@ "when": "false" }, { - "command": "codev.devServer.stop", - "when": "codev.devServerRunning" + "command": "codev.dev.stop", + "when": "codev.devRunning" }, { - "command": "codev.devServer.restart", - "when": "codev.devServerRunning" + "command": "codev.dev.restart", + "when": "codev.devRunning" }, { - "command": "codev.devServer.switchTarget", + "command": "codev.dev.switchTarget", "when": "codev.hasDevCommand" }, { - "command": "codev.devServer.showSidebar", + "command": "codev.dev.showSidebar", "when": "false" }, { - "command": "codev.devServer.hideSidebar", + "command": "codev.dev.hideSidebar", "when": "false" } ], @@ -710,28 +710,28 @@ "group": "navigation" }, { - "command": "codev.devServer.stop", - "when": "view == codev.devServer && codev.devServerRunning", + "command": "codev.dev.stop", + "when": "view == codev.dev && codev.devRunning", "group": "navigation@1" }, { - "command": "codev.devServer.restart", - "when": "view == codev.devServer && codev.devServerRunning", + "command": "codev.dev.restart", + "when": "view == codev.dev && codev.devRunning", "group": "navigation@2" }, { - "command": "codev.devServer.switchTarget", - "when": "view == codev.devServer", + "command": "codev.dev.switchTarget", + "when": "view == codev.dev", "group": "navigation@3" }, { - "command": "codev.devServer.showSidebar", - "when": "view == codev.devServer && !(sideBarVisible && activeViewlet == 'workbench.view.extension.codev')", + "command": "codev.dev.showSidebar", + "when": "view == codev.dev && !(sideBarVisible && activeViewlet == 'workbench.view.extension.codev')", "group": "navigation@4" }, { - "command": "codev.devServer.hideSidebar", - "when": "view == codev.devServer && sideBarVisible && activeViewlet == 'workbench.view.extension.codev'", + "command": "codev.dev.hideSidebar", + "when": "view == codev.dev && sideBarVisible && activeViewlet == 'workbench.view.extension.codev'", "group": "navigation@4" } ], @@ -871,7 +871,7 @@ ], "codevPanel": [ { "id": "codev.placeholder", "name": "Codev", "when": "codev.panelContainerEmpty", "visibility": "collapsed" }, - { "id": "codev.devServer", "name": "Codev Dev" } + { "id": "codev.dev", "name": "Codev Dev" } ] }, "viewsWelcome": [ diff --git a/packages/vscode/src/__tests__/contributes-dev-server.test.ts b/packages/vscode/src/__tests__/contributes-dev-server.test.ts deleted file mode 100644 index 1557e193c..000000000 --- a/packages/vscode/src/__tests__/contributes-dev-server.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Contributes invariants for the Codev Dev surface (#921): - * - the `codev.devServer` view is the real tab in #812's `codevPanel` container; - * - extension.ts flips `codev.panelContainerEmpty` false (so #812's placeholder - * yields) and registers the view + the chip refresh; - * - the four title-bar actions are declared with icons and the right `when` - * gating (Stop/Restart only while running; Switch/Reveal always). - */ - -import { describe, it, expect } from 'vitest'; -import { readFileSync } from 'node:fs'; -import { resolve } from 'node:path'; - -const ROOT = resolve(__dirname, '../..'); -const PKG = JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf8')); -const EXT_SRC = readFileSync(resolve(ROOT, 'src/extension.ts'), 'utf8'); - -interface View { id: string; name: string; when?: string } -interface Menu { command: string; when?: string; group?: string } -interface Command { command: string; title: string; icon?: string } - -const views = PKG.contributes.views as Record; -const titleMenus = (PKG.contributes.menus['view/title'] ?? []) as Menu[]; -const commands = PKG.contributes.commands as Command[]; - -describe('codev.devServer view (#921)', () => { - it('lives in the codevPanel container with the title "Codev Dev"', () => { - const dev = (views.codevPanel ?? []).find((v) => v.id === 'codev.devServer'); - expect(dev).toBeDefined(); - expect(dev!.name).toBe('Codev Dev'); - // Always present (no `when`), so the container is never empty. - expect(dev!.when).toBeUndefined(); - }); -}); - -describe('codev.devServer title-bar actions (#921)', () => { - const action = (command: string) => titleMenus.find((m) => m.command === command); - - it('declares Stop/Restart gated on a running dev', () => { - for (const cmd of ['codev.devServer.stop', 'codev.devServer.restart']) { - expect(action(cmd)?.when).toBe('view == codev.devServer && codev.devServerRunning'); - } - }); - - it('shows Switch Target whenever the view is active', () => { - expect(action('codev.devServer.switchTarget')?.when).toBe('view == codev.devServer'); - }); - - it('pairs Reveal / Hide as a sidebar toggle on the Codev viewlet visibility', () => { - const codevSidebarShown = "sideBarVisible && activeViewlet == 'workbench.view.extension.codev'"; - // Reveal shows when the Codev sidebar is NOT the active, visible viewlet. - expect(action('codev.devServer.showSidebar')?.when) - .toBe(`view == codev.devServer && !(${codevSidebarShown})`); - // Hide shows when it is — the complementary half of the toggle. - expect(action('codev.devServer.hideSidebar')?.when) - .toBe(`view == codev.devServer && ${codevSidebarShown}`); - }); - - it('gives each action an icon', () => { - const byId = Object.fromEntries(commands.map((c) => [c.command, c])); - expect(byId['codev.devServer.stop']?.icon).toBe('$(debug-stop)'); - expect(byId['codev.devServer.restart']?.icon).toBe('$(debug-restart)'); - expect(byId['codev.devServer.switchTarget']?.icon).toBe('$(arrow-swap)'); - expect(byId['codev.devServer.showSidebar']?.icon).toBe('$(eye)'); - expect(byId['codev.devServer.hideSidebar']?.icon).toBe('$(eye-closed)'); - }); -}); - -describe('extension.ts wiring (#921)', () => { - it('creates the dev-server tree view via createTreeView (for the badge handle)', () => { - expect(EXT_SRC).toMatch( - /createTreeView\(['"]codev\.devServer['"], \{ treeDataProvider: devServerProvider \}\)/, - ); - }); - - it('drives the chip + devServerRunning context key + tab badge off the dev-terminal event', () => { - expect(EXT_SRC).toMatch(/onDidChangeDevTerminals\(refreshDevSurface\)/); - expect(EXT_SRC).toMatch(/setContext['"],\s*['"]codev\.devServerRunning['"]/); - expect(EXT_SRC).toMatch(/devServerView\.badge\s*=/); - }); -}); diff --git a/packages/vscode/src/__tests__/contributes-dev.test.ts b/packages/vscode/src/__tests__/contributes-dev.test.ts new file mode 100644 index 000000000..3bf7ef6a5 --- /dev/null +++ b/packages/vscode/src/__tests__/contributes-dev.test.ts @@ -0,0 +1,113 @@ +/** + * Contributes invariants for the Codev Dev surface (#921): + * - the `codev.dev` view is the real tab in #812's `codevPanel` container; + * - extension.ts flips `codev.panelContainerEmpty` false (so #812's placeholder + * yields) and registers the view + the chip refresh; + * - the four title-bar actions are declared with icons and the right `when` + * gating (Stop/Restart only while running; Switch/Reveal always). + */ + +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const ROOT = resolve(__dirname, '../..'); +const PKG = JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf8')); +const EXT_SRC = readFileSync(resolve(ROOT, 'src/extension.ts'), 'utf8'); + +interface View { id: string; name: string; when?: string } +interface Menu { command: string; when?: string; group?: string } +interface Command { command: string; title: string; icon?: string } + +const views = PKG.contributes.views as Record; +const titleMenus = (PKG.contributes.menus['view/title'] ?? []) as Menu[]; +const commands = PKG.contributes.commands as Command[]; + +describe('codev.dev view (#921)', () => { + it('lives in the codevPanel container with the title "Codev Dev"', () => { + const dev = (views.codevPanel ?? []).find((v) => v.id === 'codev.dev'); + expect(dev).toBeDefined(); + expect(dev!.name).toBe('Codev Dev'); + // Always present (no `when`), so the container is never empty. + expect(dev!.when).toBeUndefined(); + }); +}); + +describe('codev.dev title-bar actions (#921)', () => { + const action = (command: string) => titleMenus.find((m) => m.command === command); + + it('declares Stop/Restart gated on a running dev', () => { + for (const cmd of ['codev.dev.stop', 'codev.dev.restart']) { + expect(action(cmd)?.when).toBe('view == codev.dev && codev.devRunning'); + } + }); + + it('shows Switch Target whenever the view is active', () => { + expect(action('codev.dev.switchTarget')?.when).toBe('view == codev.dev'); + }); + + it('pairs Reveal / Hide as a sidebar toggle on the Codev viewlet visibility', () => { + const codevSidebarShown = "sideBarVisible && activeViewlet == 'workbench.view.extension.codev'"; + // Reveal shows when the Codev sidebar is NOT the active, visible viewlet. + expect(action('codev.dev.showSidebar')?.when) + .toBe(`view == codev.dev && !(${codevSidebarShown})`); + // Hide shows when it is — the complementary half of the toggle. + expect(action('codev.dev.hideSidebar')?.when) + .toBe(`view == codev.dev && ${codevSidebarShown}`); + }); + + it('gives each action an icon', () => { + const byId = Object.fromEntries(commands.map((c) => [c.command, c])); + expect(byId['codev.dev.stop']?.icon).toBe('$(debug-stop)'); + expect(byId['codev.dev.restart']?.icon).toBe('$(debug-restart)'); + expect(byId['codev.dev.switchTarget']?.icon).toBe('$(arrow-swap)'); + expect(byId['codev.dev.showSidebar']?.icon).toBe('$(eye)'); + expect(byId['codev.dev.hideSidebar']?.icon).toBe('$(eye-closed)'); + }); +}); + +describe('extension.ts wiring (#921)', () => { + it('creates the dev tree view via createTreeView (for the badge handle)', () => { + expect(EXT_SRC).toMatch( + /createTreeView\(['"]codev\.dev['"], \{ treeDataProvider: devProvider \}\)/, + ); + }); + + it('drives the chip + devRunning context key + tab badge off the dev-terminal event', () => { + expect(EXT_SRC).toMatch(/onDidChangeDevTerminals\(refreshDevSurface\)/); + expect(EXT_SRC).toMatch(/setContext['"],\s*['"]codev\.devRunning['"]/); + expect(EXT_SRC).toMatch(/devView\.badge\s*=/); + }); +}); + +// Regression guard for #1158: the runnable-worktrees surfaces must read "dev", +// never "dev server" / "devServer". The abstraction is stack-agnostic (a dev +// server, `cargo run`, `expo start`, a test watcher, a build script, …), so the +// web-centric "Server" wording is banned from every command title and id. This +// fails loudly if a title or id ever reintroduces the term. +describe('#1158: no "dev server" terminology on VS Code surfaces', () => { + const devCommands = commands.filter( + (c) => /\bdev\b/i.test(c.command) || /\bdev\b/i.test(c.title), + ); + + it('has dev commands to check (guards against a silently empty filter)', () => { + expect(devCommands.length).toBeGreaterThan(0); + }); + + it('no command title contains "Server"', () => { + const offenders = devCommands.filter((c) => /server/i.test(c.title)); + expect(offenders.map((c) => c.title)).toEqual([]); + }); + + it('no command id contains "devServer"', () => { + const offenders = commands.filter((c) => c.command.includes('devServer')); + expect(offenders.map((c) => c.command)).toEqual([]); + }); + + it('no view id or menu when-clause references codev.devServer', () => { + const allViews = Object.values(views).flat(); + expect(allViews.filter((v) => v.id.includes('devServer')).map((v) => v.id)).toEqual([]); + const wheres = titleMenus.map((m) => m.when ?? '').filter((w) => w.includes('devServer')); + expect(wheres).toEqual([]); + }); +}); diff --git a/packages/vscode/src/__tests__/contributes-panel.test.ts b/packages/vscode/src/__tests__/contributes-panel.test.ts index 09b85a6d9..5782845d3 100644 --- a/packages/vscode/src/__tests__/contributes-panel.test.ts +++ b/packages/vscode/src/__tests__/contributes-panel.test.ts @@ -7,9 +7,9 @@ * - the existing sidebar views are unchanged (regression guard); * - extension.ts wires the placeholder provider and the context key. * - * Note: once #921 added the real `codev.devServer` view, the panel is no longer + * Note: once #921 added the real `codev.dev` view, the panel is no longer * empty — the context key is seeded `false` and a second view is present. Those - * invariants are covered in contributes-dev-server.test.ts; this file keeps the + * invariants are covered in contributes-dev.test.ts; this file keeps the * #812 scaffolding guards (placeholder shape, sidebar regression). */ diff --git a/packages/vscode/src/__tests__/dev-server-format.test.ts b/packages/vscode/src/__tests__/dev-format.test.ts similarity index 98% rename from packages/vscode/src/__tests__/dev-server-format.test.ts rename to packages/vscode/src/__tests__/dev-format.test.ts index 628d15422..eec656f3c 100644 --- a/packages/vscode/src/__tests__/dev-server-format.test.ts +++ b/packages/vscode/src/__tests__/dev-format.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { formatUptime, extractDevPort, formatTargetName } from '../views/dev-server-format.js'; +import { formatUptime, extractDevPort, formatTargetName } from '../views/dev-format.js'; describe('formatUptime', () => { it('renders sub-minute durations as seconds', () => { diff --git a/packages/vscode/src/__tests__/has-runnable-dev-command.test.ts b/packages/vscode/src/__tests__/has-runnable-dev-command.test.ts index ca491c371..58947f325 100644 --- a/packages/vscode/src/__tests__/has-runnable-dev-command.test.ts +++ b/packages/vscode/src/__tests__/has-runnable-dev-command.test.ts @@ -3,7 +3,7 @@ * * This helper is the single source of truth for "is there a runnable * worktree.devCommand" across two surfaces: the `codev.hasDevCommand` - * context key (gates the builder-row Run/Stop Dev Server menu) and the + * context key (gates the builder-row Run/Stop Dev menu) and the * Workspace view's Start-row visibility. The critical case is the empty * string: `ResolvedWorktreeConfig.devCommand` is typed `string | null`, so * `""` is reachable, and it must be treated as absent (matching diff --git a/packages/vscode/src/__tests__/menu-when-clauses.test.ts b/packages/vscode/src/__tests__/menu-when-clauses.test.ts index baeaea6f0..3136ae65a 100644 --- a/packages/vscode/src/__tests__/menu-when-clauses.test.ts +++ b/packages/vscode/src/__tests__/menu-when-clauses.test.ts @@ -125,9 +125,9 @@ describe('commandPalette hiding for view{Spec,Plan,Review}File', () => { }); /** - * `codev.hasDevCommand` gating for the dev-server commands (#975). + * `codev.hasDevCommand` gating for the dev commands (#975). * - * The builder-row Run/Stop Dev Server context-menu entries must only + * The builder-row Run/Stop Dev context-menu entries must only * surface when a runnable `worktree.devCommand` is configured. Previously * they gated on view + viewItem family only, so they showed even with no * dev command — picking one ran against a missing command. The fix appends @@ -144,7 +144,7 @@ describe('commandPalette hiding for view{Spec,Plan,Review}File', () => { * silently re-expose a command that can't run — no compile/runtime error * would catch it. */ -describe('codev.hasDevCommand gating for dev-server commands', () => { +describe('codev.hasDevCommand gating for dev commands', () => { const paletteEntries: Array<{ command: string; when?: string }> = PKG.contributes.menus.commandPalette; const keybindings: Array<{ command: string; when?: string }> = diff --git a/packages/vscode/src/__tests__/terminal-manager.test.ts b/packages/vscode/src/__tests__/terminal-manager.test.ts index c7b607caa..7453c5e2b 100644 --- a/packages/vscode/src/__tests__/terminal-manager.test.ts +++ b/packages/vscode/src/__tests__/terminal-manager.test.ts @@ -135,7 +135,7 @@ describe('#804 — builder/shell terminals do not force-create a second editor g describe('#921 — dev surface refresh on manual terminal close', () => { // Regression guard: a dev terminal closed via the generic onDidCloseTerminal // path (tab ✕ / process exit) must clear devStartedAt AND re-fire - // onDidChangeDevTerminals, or the chip / Codev Dev tab / devServerRunning + // onDidChangeDevTerminals, or the chip / Codev Dev tab / devRunning // context strand as "running". The explicit close paths fired the event; the // generic path previously only unmapped. Source-level per this file's harness // rationale (constructing TerminalManager needs heavy vscode mocking). diff --git a/packages/vscode/src/command-relay.ts b/packages/vscode/src/command-relay.ts index dae3fd3b5..15dd10d8e 100644 --- a/packages/vscode/src/command-relay.ts +++ b/packages/vscode/src/command-relay.ts @@ -48,7 +48,7 @@ const VERB_COMMANDS: Record = { // Viewport scroll of the focused editor (the Scroll dial). Args carry the // built-in editorScroll options { to, by, value, revealCursor }. 'scroll': 'editorScroll', - // Workspace verbs (configurable Codev Action key / Dev Server key). + // Workspace verbs (configurable Codev Action key / Dev key). 'focus-workspace': 'codev.focusWorkspaceWindow', 'open-architect-terminal': 'codev.openArchitectTerminal', 'open-builder-terminal': 'codev.openBuilderTerminal', diff --git a/packages/vscode/src/commands/dev-server-actions.ts b/packages/vscode/src/commands/dev-actions.ts similarity index 94% rename from packages/vscode/src/commands/dev-server-actions.ts rename to packages/vscode/src/commands/dev-actions.ts index 78ceaead0..098660101 100644 --- a/packages/vscode/src/commands/dev-server-actions.ts +++ b/packages/vscode/src/commands/dev-actions.ts @@ -17,7 +17,7 @@ import { } from './dev-shared.js'; /** Stop the running dev. Single-slot, so this is the one dev in the registry. */ -export async function stopDevServer( +export async function stopDev( connectionManager: ConnectionManager, terminalManager: TerminalManager, ): Promise { @@ -25,13 +25,13 @@ export async function stopDevServer( } /** Stop and respawn the dev for whatever target is currently running. */ -export async function restartDevServer( +export async function restartDev( connectionManager: ConnectionManager, terminalManager: TerminalManager, ): Promise { const running = terminalManager.listDevTerminals()[0]; if (!running) { - vscode.window.showInformationMessage('Codev: No dev server is running'); + vscode.window.showInformationMessage('Codev: No dev is running'); return; } const target = await resolveDevTargetById(connectionManager, running.builderId); @@ -67,7 +67,7 @@ export async function switchDevTarget( } /** - * Open the Codev sidebar and focus the Workspace view, where the Dev Server row + * Open the Codev sidebar and focus the Workspace view, where the Dev row * lives. Paired with `hideCodevSidebar` to form a show/hide toggle on the tab's * title bar (the two `view/title` entries swap on the sidebar-visibility context * keys, mirroring the Backlog view's show-all / mine-only toggle). diff --git a/packages/vscode/src/commands/dev-shared.ts b/packages/vscode/src/commands/dev-shared.ts index 8a9e4163a..e13aec089 100644 --- a/packages/vscode/src/commands/dev-shared.ts +++ b/packages/vscode/src/commands/dev-shared.ts @@ -1,5 +1,5 @@ /** - * Shared core for Codev dev-server commands. There is exactly one underlying + * Shared core for Codev dev commands. There is exactly one underlying * action — "spawn a Tower dev PTY for a {id, cwd} target and open its tab" — * with two front-ends that differ only in how they resolve the target: * @@ -243,7 +243,7 @@ export async function stopDevForTarget( } const found = terminalManager.listDevTerminals().find(d => d.builderId === targetId); if (!found) { - vscode.window.showInformationMessage(`Codev: No dev server is running for ${name}`); + vscode.window.showInformationMessage(`Codev: No dev is running for ${name}`); return; } await client.killTerminal(found.terminalId); diff --git a/packages/vscode/src/commands/run-workspace-dev.ts b/packages/vscode/src/commands/run-workspace-dev.ts index 486abad96..75b764afe 100644 --- a/packages/vscode/src/commands/run-workspace-dev.ts +++ b/packages/vscode/src/commands/run-workspace-dev.ts @@ -1,5 +1,5 @@ /** - * Codev: Start / Stop Dev Server (Workspace view) — runs the dev server for + * Codev: Start / Stop Dev (Workspace view) — runs the dev for * whatever folder *this VSCode window is rooted at*. Not "main"-specific: * * - window opened on the main checkout → target `main`, cwd = root diff --git a/packages/vscode/src/commands/run-worktree-dev.ts b/packages/vscode/src/commands/run-worktree-dev.ts index cea6c97af..4df60c6f5 100644 --- a/packages/vscode/src/commands/run-worktree-dev.ts +++ b/packages/vscode/src/commands/run-worktree-dev.ts @@ -1,5 +1,5 @@ /** - * Codev: Run Dev Server — start a Tower-managed dev PTY for a builder's + * Codev: Run Dev — start a Tower-managed dev PTY for a builder's * worktree. Right-click a builder row (or palette quick-pick) resolves the * builder from Tower's overview, then delegates to the shared dev core * (dev-shared.ts), which handles the devCommand read, swap, spawn, and tab diff --git a/packages/vscode/src/commands/stop-worktree-dev.ts b/packages/vscode/src/commands/stop-worktree-dev.ts index feff76ca6..4fa0a95e2 100644 --- a/packages/vscode/src/commands/stop-worktree-dev.ts +++ b/packages/vscode/src/commands/stop-worktree-dev.ts @@ -1,5 +1,5 @@ /** - * Codev: Stop Dev Server — kill the currently running Codev-managed dev PTY. + * Codev: Stop Dev — kill the currently running Codev-managed dev PTY. * * Counterpart to `codev.runWorktreeDev`. Asks TerminalManager which dev * terminals it has open (its local map is the source of truth — see @@ -24,7 +24,7 @@ export async function stopWorktreeDev( const devs = terminalManager.listDevTerminals(); if (devs.length === 0) { - vscode.window.showInformationMessage('Codev: No dev server is running'); + vscode.window.showInformationMessage('Codev: No dev is running'); return; } @@ -35,6 +35,6 @@ export async function stopWorktreeDev( const summary = devs.length === 1 ? `Codev: Dev server stopped for ${devs[0]!.builderId}` - : `Codev: Stopped ${devs.length} dev servers`; + : `Codev: Stopped ${devs.length} devs`; vscode.window.showInformationMessage(summary); } diff --git a/packages/vscode/src/extension.ts b/packages/vscode/src/extension.ts index 9e2be6ef9..3d9ed666e 100644 --- a/packages/vscode/src/extension.ts +++ b/packages/vscode/src/extension.ts @@ -18,7 +18,7 @@ import { buildBuilderRangeRef, buildBuilderFileRef } from './diff-inject-ref.js' import { runWorktreeDev } from './commands/run-worktree-dev.js'; import { stopWorktreeDev } from './commands/stop-worktree-dev.js'; import { runWorkspaceDev, stopWorkspaceDev } from './commands/run-workspace-dev.js'; -import { stopDevServer, restartDevServer, switchDevTarget, showCodevSidebar, hideCodevSidebar } from './commands/dev-server-actions.js'; +import { stopDev, restartDev, switchDevTarget, showCodevSidebar, hideCodevSidebar } from './commands/dev-actions.js'; import { openDevUrl } from './commands/open-dev-url.js'; import { pasteImage } from './commands/paste-image.js'; import { openWorktreeFolder } from './commands/open-worktree-folder.js'; @@ -49,8 +49,8 @@ import { RecentlyClosedProvider } from './views/recently-closed.js'; import { TeamProvider } from './views/team.js'; import { StatusProvider } from './views/status.js'; import { PanelPlaceholderProvider } from './views/panel-placeholder.js'; -import { DevServerTreeProvider } from './views/dev-server.js'; -import { formatTargetName } from './views/dev-server-format.js'; +import { DevTreeProvider } from './views/dev.js'; +import { formatTargetName } from './views/dev-format.js'; import { WorkspaceProvider } from './views/workspace.js'; import { displayArchitectName, sortArchitectsForPicker } from './views/architect-display.js'; import { validateArchitectName } from '@cluesmith/codev-core/architect-name'; @@ -297,7 +297,7 @@ export async function activate(context: vscode.ExtensionContext) { // the async hook fetch and publish into an empty cache. // Drive the `codev.hasDevCommand` context key so the builder-row Run/Stop - // Dev Server menu entries, the dev keybindings, and the workspace-dev palette + // Dev menu entries, the dev keybindings, and the workspace-dev palette // entries only surface when a runnable `worktree.devCommand` is configured // (#975). These surfaces are global (the keybindings/palette are invokable // regardless of whether the Builders tree has rendered), so the key is @@ -509,8 +509,8 @@ export async function activate(context: vscode.ExtensionContext) { // Codev Dev panel tab (#921) — the first real view in #812's codevPanel. // createTreeView (not registerTreeDataProvider) so we hold the handle and can // set TreeView.badge — the activity dot the plan calls for while a dev runs. - const devServerProvider = new DevServerTreeProvider(connectionManager, terminalManager!); - const devServerView = vscode.window.createTreeView('codev.devServer', { treeDataProvider: devServerProvider }); + const devProvider = new DevTreeProvider(connectionManager, terminalManager!); + const devView = vscode.window.createTreeView('codev.dev', { treeDataProvider: devProvider }); context.subscriptions.push( buildersView, pullRequestsView, @@ -520,12 +520,12 @@ export async function activate(context: vscode.ExtensionContext) { vscode.window.registerTreeDataProvider('codev.team', teamProvider), vscode.window.registerTreeDataProvider('codev.status', statusProvider), vscode.window.registerTreeDataProvider('codev.placeholder', new PanelPlaceholderProvider()), - devServerView, - { dispose: () => devServerProvider.dispose() }, + devView, + { dispose: () => devProvider.dispose() }, ); // Panel container (#812) ships a placeholder signpost gated by - // `codev.panelContainerEmpty`. codev.devServer (#921) is a real, always-present + // `codev.panelContainerEmpty`. codev.dev (#921) is a real, always-present // panel view, so the container is never empty — flip the key false to hide the // signpost. (Sibling tabs #813/#814/#815 set the same key; idempotent.) vscode.commands.executeCommand('setContext', 'codev.panelContainerEmpty', false); @@ -538,15 +538,15 @@ export async function activate(context: vscode.ExtensionContext) { if (target) { if (!devChipItem) { devChipItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); - devChipItem.command = 'codev.devServer.focus'; // VSCode's auto view-focus command + devChipItem.command = 'codev.dev.focus'; // VSCode's auto view-focus command } - // server-process (a running dev server), not zap — $(zap) reads as AI/sparkle in VSCode. + // server-process (a running dev), not zap — $(zap) reads as AI/sparkle in VSCode. devChipItem.text = `$(server-process) Dev: ${target}`; // StatusBarItem.backgroundColor only honors error/warning backgrounds // (VSCode API constraint), so the "prominent, not alarming" look // (#921 design call #4) is applied via the foreground instead. devChipItem.color = new vscode.ThemeColor('statusBarItem.prominentForeground'); - devChipItem.tooltip = `Codev dev server running for ${target}. Click to focus Codev Dev panel`; + devChipItem.tooltip = `Codev dev running for ${target}. Click to focus Codev Dev panel`; devChipItem.show(); } else if (devChipItem) { devChipItem.dispose(); @@ -557,11 +557,11 @@ export async function activate(context: vscode.ExtensionContext) { const builderId = terminalManager?.listDevTerminals()[0]?.builderId ?? null; const target = builderId ? formatTargetName(builderId) : null; updateDevChip(target); - vscode.commands.executeCommand('setContext', 'codev.devServerRunning', target !== null); + vscode.commands.executeCommand('setContext', 'codev.devRunning', target !== null); // Activity dot on the Codev Dev tab while a dev runs — visible when the // user is on another codevPanel tab (plan's tab-badge requirement). - devServerView.badge = target - ? { value: 1, tooltip: `Dev server running for ${target}` } + devView.badge = target + ? { value: 1, tooltip: `Dev running for ${target}` } : undefined; }; context.subscriptions.push( @@ -1228,15 +1228,15 @@ export async function activate(context: vscode.ExtensionContext) { runWorkspaceDev(connectionManager!, terminalManager!)), regCli('codev.stopWorkspaceDev', () => stopWorkspaceDev(connectionManager!, terminalManager!)), - regCli('codev.devServer.stop', () => - stopDevServer(connectionManager!, terminalManager!)), - regCli('codev.devServer.restart', () => - restartDevServer(connectionManager!, terminalManager!)), - regCli('codev.devServer.switchTarget', () => + regCli('codev.dev.stop', () => + stopDev(connectionManager!, terminalManager!)), + regCli('codev.dev.restart', () => + restartDev(connectionManager!, terminalManager!)), + regCli('codev.dev.switchTarget', () => switchDevTarget(connectionManager!, terminalManager!)), - reg('codev.devServer.showSidebar', () => + reg('codev.dev.showSidebar', () => showCodevSidebar()), - reg('codev.devServer.hideSidebar', () => + reg('codev.dev.hideSidebar', () => hideCodevSidebar()), reg('codev.openDevUrl', (urlArg?: unknown) => openDevUrl(connectionManager!, typeof urlArg === 'string' ? urlArg : undefined)), diff --git a/packages/vscode/src/load-worktree-config.ts b/packages/vscode/src/load-worktree-config.ts index 87da4f45a..f4e3069fc 100644 --- a/packages/vscode/src/load-worktree-config.ts +++ b/packages/vscode/src/load-worktree-config.ts @@ -42,7 +42,7 @@ export async function loadWorktreeConfig( * is reachable and must be treated as absent, not present-but-disabled. * * Single source of truth for two surfaces: the `codev.hasDevCommand` - * context key (gates the builder-row Run/Stop Dev Server menu) and the + * context key (gates the builder-row Run/Stop Dev menu) and the * Workspace view's Start-row visibility. Keeping both on this helper * guarantees they agree on every config state. */ diff --git a/packages/vscode/src/terminal-manager.ts b/packages/vscode/src/terminal-manager.ts index 50e2fa450..ffa23eb40 100644 --- a/packages/vscode/src/terminal-manager.ts +++ b/packages/vscode/src/terminal-manager.ts @@ -303,12 +303,12 @@ export class TerminalManager { } /** - * Open a dev-server terminal for a builder's worktree (#690). + * Open a dev terminal for a builder's worktree (#690). * Keyed `dev-` so it lives alongside (not on top of) the * builder's own AI terminal at `builder-`. Tab label is set by the * caller (server-side `'Dev: '` flows through Tower's terminal name). * - * `focus` defaults to true — `afx dev` / "Run Dev Server" are explicit + * `focus` defaults to true — `afx dev` / "Run Dev" are explicit * user actions, so activate the tab so they see the spawning output. */ async openDevTerminal(terminalId: string, builderId: string, builderName: string, focus = true): Promise { @@ -344,7 +344,7 @@ export class TerminalManager { } /** - * Dispose the VSCode terminal tab for a builder's dev server, if any. + * Dispose the VSCode terminal tab for a builder's dev, if any. * Used by `codev.stopWorktreeDev` after killing the Tower-side PTY so the * user doesn't see a dead "Process exited" tab lingering. */ @@ -361,7 +361,7 @@ export class TerminalManager { /** * Dispose the VSCode terminal tabs for a builder — both the AI terminal - * and any companion dev-server terminal — after the builder has been + * and any companion dev terminal — after the builder has been * cleaned up. Tower kills the PTYs as part of cleanup, so without this * the user sees a stale "Process exited" tab until they close it * manually. Accepts the canonical builder roleId (e.g. `builder-spir-109`), @@ -521,7 +521,7 @@ export class TerminalManager { // exiting) must refresh the dev surfaces (#921) too — the explicit // closeDevTerminal/closeBuilderTerminal paths fire the event, but a manual // close reaches only here, which previously just unmapped and left the - // chip / tab / `codev.devServerRunning` stranded as "running". Guarded by + // chip / tab / `codev.devRunning` stranded as "running". Guarded by // `wasTracked` so the explicit-close path (which deletes first, then // dispose()s the terminal) doesn't double-fire. if (wasTracked && mapKey.startsWith('dev-')) { diff --git a/packages/vscode/src/views/dev-server-format.ts b/packages/vscode/src/views/dev-format.ts similarity index 100% rename from packages/vscode/src/views/dev-server-format.ts rename to packages/vscode/src/views/dev-format.ts diff --git a/packages/vscode/src/views/dev-server.ts b/packages/vscode/src/views/dev.ts similarity index 97% rename from packages/vscode/src/views/dev-server.ts rename to packages/vscode/src/views/dev.ts index da1d4e044..21cd1267b 100644 --- a/packages/vscode/src/views/dev-server.ts +++ b/packages/vscode/src/views/dev.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; import type { ConnectionManager } from '../connection-manager.js'; import type { TerminalManager } from '../terminal-manager.js'; import { loadWorktreeConfig } from '../load-worktree-config.js'; -import { formatUptime, extractDevPort, formatTargetName } from './dev-server-format.js'; +import { formatUptime, extractDevPort, formatTargetName } from './dev-format.js'; /** * The "Codev Dev" panel tab (#921). A status surface for the single `afx dev` @@ -16,7 +16,7 @@ import { formatUptime, extractDevPort, formatTargetName } from './dev-server-for * at most one dev). We re-derive on every `onDidChangeDevTerminals` and keep a * 1s ticker running while a dev is up so the uptime row stays live. */ -export class DevServerTreeProvider implements vscode.TreeDataProvider { +export class DevTreeProvider implements vscode.TreeDataProvider { private readonly _onDidChangeTreeData = new vscode.EventEmitter(); readonly onDidChangeTreeData = this._onDidChangeTreeData.event; @@ -37,7 +37,7 @@ export class DevServerTreeProvider implements vscode.TreeDataProvider Date: Mon, 13 Jul 2026 13:33:47 +0700 Subject: [PATCH 4/8] chore(porch): bugfix-1158 pr phase-transition --- .../bugfix-1158-vscode-strip-dev-server-termin/status.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml index e1a29e366..f00062134 100644 --- a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml +++ b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml @@ -1,7 +1,7 @@ id: bugfix-1158 title: vscode-strip-dev-server-termin protocol: bugfix -phase: fix +phase: pr plan_phases: [] current_plan_phase: null gates: @@ -11,4 +11,4 @@ iteration: 1 build_complete: false history: [] started_at: '2026-07-13T06:12:19.993Z' -updated_at: '2026-07-13T06:17:03.100Z' +updated_at: '2026-07-13T06:33:47.784Z' From f931aa4e779c7ba9cf596a37c154ad6d3377899e Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Mon, 13 Jul 2026 13:42:16 +0700 Subject: [PATCH 5/8] [Bugfix #1158] Fix: strip remaining "Dev server" strings caught by CMAP 3-way CMAP review (gemini + codex + claude, all REQUEST_CHANGES on the same defect) caught user-facing toast strings the first pass missed. Root cause: the initial verification grep was case-sensitive and skipped the mixed-case "Dev server" variant. - dev-shared.ts / stop-worktree-dev.ts: "Codev: Dev server started/stopped/already running for ..." -> "Codev: Dev started/stopped/is already running for ..." (runtime showInformationMessage toasts). - terminal-manager.ts / workspace.ts: comment wording ("Dev servers are ...", the "Stop Dev Server" row reference). - README.md (marketplace doc): command titles now match the renamed palette (Run/Stop/Start Dev), prose neutralized, and the intro enumerates the range (dev server, cargo run, expo start, test watcher, build script) so non-web users don't self-exclude. - pir/protocol.md (both trees): "at-gate dev-server review flow" -> "dev review flow". - contributes-dev.test.ts: strengthen the #1158 guard to scan EVERY contributed menu group and all keybindings for a reintroduced devServer id/when-clause (previously only view/title was checked). Case-insensitive grep of packages/vscode for dev-server terminology now returns only the intentional stack-agnostic enumeration. 590 unit tests pass; compile clean. --- codev-skeleton/protocols/pir/protocol.md | 2 +- codev/protocols/pir/protocol.md | 2 +- packages/vscode/README.md | 34 +++++++++---------- .../src/__tests__/contributes-dev.test.ts | 25 ++++++++++++-- packages/vscode/src/commands/dev-shared.ts | 6 ++-- .../vscode/src/commands/stop-worktree-dev.ts | 2 +- packages/vscode/src/terminal-manager.ts | 2 +- packages/vscode/src/views/workspace.ts | 4 +-- 8 files changed, 48 insertions(+), 29 deletions(-) diff --git a/codev-skeleton/protocols/pir/protocol.md b/codev-skeleton/protocols/pir/protocol.md index 0e68f92f8..b3befc173 100644 --- a/codev-skeleton/protocols/pir/protocol.md +++ b/codev-skeleton/protocols/pir/protocol.md @@ -134,7 +134,7 @@ This means typed input in the builder pane reaches the live Claude session immed ## Configuration -PIR uses the same `.codev/config.json` configuration as other protocols. The `worktree` block (from Issue 689) enables the at-gate dev-server review flow: +PIR uses the same `.codev/config.json` configuration as other protocols. The `worktree` block (from Issue 689) enables the at-gate dev review flow: ```json { diff --git a/codev/protocols/pir/protocol.md b/codev/protocols/pir/protocol.md index 0e68f92f8..b3befc173 100644 --- a/codev/protocols/pir/protocol.md +++ b/codev/protocols/pir/protocol.md @@ -134,7 +134,7 @@ This means typed input in the builder pane reaches the live Claude session immed ## Configuration -PIR uses the same `.codev/config.json` configuration as other protocols. The `worktree` block (from Issue 689) enables the at-gate dev-server review flow: +PIR uses the same `.codev/config.json` configuration as other protocols. The `worktree` block (from Issue 689) enables the at-gate dev review flow: ```json { diff --git a/packages/vscode/README.md b/packages/vscode/README.md index f55387427..f249bfced 100644 --- a/packages/vscode/README.md +++ b/packages/vscode/README.md @@ -1,12 +1,12 @@ # Codev for VS Code -Bring Codev's Agent Farm into VS Code — monitor builders, open terminals, approve gates, run dev servers, and manage your development workflow without leaving the IDE. +Bring Codev's Agent Farm into VS Code — monitor builders, open terminals, approve gates, run dev commands, and manage your development workflow without leaving the IDE. ## Features - **Unified sidebar** — Workspace, Agents, Pull Requests, Backlog, Recently Closed, Team, and Status in a single pane. Blocked builders are flagged inline in Agents; live item counts appear in view titles. -- **Native terminals** — Architect / builder / shell terminals in the editor area; dev servers in the bottom panel. -- **One-click dev servers** — Start / Stop the dev server for the current workspace or any builder worktree from the sidebar (`Cmd/Ctrl+Alt+R` / `Cmd/Ctrl+Alt+S`). One runs at a time and swaps on demand. Configurable via `worktree.devCommand` in `.codev/config.json` — see the **Dev servers and runnable worktrees** section below. +- **Native terminals** — Architect / builder / shell terminals in the editor area; dev processes in the bottom panel. +- **One-click dev** — Start / Stop the dev process for the current workspace or any builder worktree from the sidebar (`Cmd/Ctrl+Alt+R` / `Cmd/Ctrl+Alt+S`). One runs at a time and swaps on demand. Configurable via `worktree.devCommand` in `.codev/config.json` — see the **Dev and runnable worktrees** section below. - **Open Dev URL rows** — surface staging / preview / tunnel links as one-click rows in the Workspace view via `worktree.devUrls`. - **Per-engineer config overrides** — `.codev/config.local.json` layers your personal settings (local devCommand, tunnel hostnames, staging URLs) over the shared project config without committing them. - **Per-builder changed files** — expand any builder row to see its diff vs main inline with native SCM-style status badges. Toggle between folder tree and flat list. @@ -26,13 +26,13 @@ Bring Codev's Agent Farm into VS Code — monitor builders, open terminals, appr 2. Open a Codev project in VS Code 3. The extension auto-detects the workspace and connects to Tower 4. Click the Codev icon in the Activity Bar to see your builders, PRs, and backlog -5. *(Optional)* Add `worktree.devCommand` to `.codev/config.json` to unlock one-click dev servers — see the **Dev servers and runnable worktrees** section below +5. *(Optional)* Add `worktree.devCommand` to `.codev/config.json` to unlock one-click dev — see the **Dev and runnable worktrees** section below ## Sidebar tour The Codev sidebar contains seven collapsible views: -- **Workspace** — Open Architect, Open Web Interface, Spawn Builder, New Shell, and Start / Stop Dev Server rows. Any `worktree.devUrls` you've configured appear here as **Open Dev URL** rows. +- **Workspace** — Open Architect, Open Web Interface, Spawn Builder, New Shell, and Start / Stop Dev rows. Any `worktree.devUrls` you've configured appear here as **Open Dev URL** rows. - **Agents** — every active builder, with status (active / blocked / waiting on input / awaiting). Builders are grouped by one of three axes, switched with the title-bar group-by button (its icon shows the axis you'll switch *to*): lifecycle **stage** (the default action axis), **area** label, or the **architect** that spawned them. In architect mode only architects that own in-flight builders appear as group headers (the full architect roster lives in Workspace > Architects). Click a row to open its terminal *and* expand its changed-files list. Right-click for the full builder action menu (see the **Builder actions (right-click)** section below). The title bar also carries buttons to toggle accordion mode and tree-vs-list file view. - **Pull Requests** — open PRs in the repo, with a live count in the title. - **Backlog** — open issues without a builder. Inline row actions drop the issue's `#` into the architect input, preview the issue, spawn a builder for it, open it in the browser, or copy the issue number. @@ -65,22 +65,22 @@ Right-click any builder in the Agents view for three grouped action menus: | Action | Description | |---|---| | Run Worktree Setup | Re-apply `worktree.symlinks` + `worktree.postSpawn` to the existing worktree (idempotent — use when the lockfile changed or config was extended after spawn) | -| Run Dev Server | Spawn the dev PTY in this builder's worktree; prompts to swap if another dev is running | -| Stop Dev Server | Kill the running dev PTY and close its tab | +| Run Dev | Spawn the dev PTY in this builder's worktree; prompts to swap if another dev is running | +| Stop Dev | Kill the running dev PTY and close its tab | -## Dev servers and runnable worktrees +## Dev and runnable worktrees -Codev can run a single dev server at a time — either for your main checkout, or for any builder's worktree — and swap between them on demand. The single-slot model is deliberate: dev PTYs reuse main's ports so OAuth callbacks, cookies, and webhooks keep working unchanged. +Codev can run a single dev process at a time — whatever your `worktree.devCommand` starts (a dev server, `cargo run`, `expo start`, a test watcher, a build script, whatever iterates on your project) — either for your main checkout, or for any builder's worktree, swapping between them on demand. The single-slot model is deliberate: dev PTYs reuse main's ports so OAuth callbacks, cookies, and webhooks keep working unchanged. ### Starting and stopping -- **For the current workspace** — the **Start Dev Server** row in the Workspace view, or `Cmd/Ctrl+Alt+R`. **Stop Dev Server** (only visible while running) or `Cmd/Ctrl+Alt+S`. -- **For a builder worktree** — right-click the builder → **Run Dev Server** / **Stop Dev Server**. +- **For the current workspace** — the **Start Dev** row in the Workspace view, or `Cmd/Ctrl+Alt+R`. **Stop Dev** (only visible while running) or `Cmd/Ctrl+Alt+S`. +- **For a builder worktree** — right-click the builder → **Run Dev** / **Stop Dev**. - Starting one target while another is already running prompts you to swap (the old PTY is killed cleanly, then the new one starts). ### Configuration: `.codev/config.json` -Add a `worktree` block to your project's `.codev/config.json`. Without `devCommand` configured, the Start Dev Server row stays hidden — it would have nothing to run. +Add a `worktree` block to your project's `.codev/config.json`. Without `devCommand` configured, the Start Dev row stays hidden — it would have nothing to run. ```jsonc { @@ -102,7 +102,7 @@ Add a `worktree` block to your project's `.codev/config.json`. Without `devComma } ``` -- **`devCommand`** — the foreground command that starts your dev server. Run by the sidebar Start Dev Server rows and the CLI (`afx dev main`, `afx dev `). +- **`devCommand`** — the foreground command that starts your dev process. Run by the sidebar Start Dev rows and the CLI (`afx dev main`, `afx dev `). - **`symlinks`** — glob patterns of files to symlink from the main checkout into each new builder worktree (env files, generated configs, etc.). Symlinks, not copies — edits in main reflect instantly in any running dev session. Root `.env` and `.codev/config.json` are always symlinked regardless. - **`postSpawn`** — shell commands run sequentially inside each new worktree after creation (e.g. `pnpm install --frozen-lockfile`). A non-zero exit aborts the spawn loudly so the half-built worktree stays for inspection. - **`devUrls`** — array of `{ label, url }` entries that show up as one-click **Open Dev URL** rows in the Workspace view. Distinct from Open Web Interface, which always points at the Tower dashboard. @@ -126,7 +126,7 @@ Both files are watched live — every open VS Code window's sidebar re-renders o ### URLs are load-bearing -Dev PTYs use the same ports as your main checkout intentionally — OAuth callbacks, CORS allowlists, cookie scoping, and webhook URLs are all keyed off origin. Before starting a sidebar dev server, stop any manually-run `pnpm dev` first, or the new PTY will fail to bind with `EADDRINUSE`. +Dev PTYs use the same ports as your main checkout intentionally — OAuth callbacks, CORS allowlists, cookie scoping, and webhook URLs are all keyed off origin. Before starting a sidebar dev, stop any manually-run `pnpm dev` first, or the new PTY will fail to bind with `EADDRINUSE`. ### Recipes for other stacks @@ -147,7 +147,7 @@ The pnpm example above adapts directly to npm / yarn / bun / cargo / poetry / go | - Team | | | | - Status | | | +------------+----------------+----------------+ -| Bottom panel: dev server (when running) | +| Bottom panel: dev (when running) | +----------------------------------------------+ ``` @@ -159,8 +159,8 @@ The pnpm example above adapts directly to npm / yarn / bun / cargo / poetry / go | `Cmd/Ctrl+K D` | Send Message (pick a builder + type a message) | | `Cmd/Ctrl+K G` | Approve Gate | | `Cmd/Ctrl+Alt+C` | Toggle the Codev sidebar (show & focus, or close if active) | -| `Cmd/Ctrl+Alt+R` | Start Dev Server (current workspace) | -| `Cmd/Ctrl+Alt+S` | Stop Dev Server (current workspace) | +| `Cmd/Ctrl+Alt+R` | Start Dev (current workspace) | +| `Cmd/Ctrl+Alt+S` | Stop Dev (current workspace) | | `Cmd/Ctrl+Alt+V` | Paste clipboard image into the focused Codev terminal — uploads to Tower and injects the saved file path | ## Commands diff --git a/packages/vscode/src/__tests__/contributes-dev.test.ts b/packages/vscode/src/__tests__/contributes-dev.test.ts index 3bf7ef6a5..163b5a478 100644 --- a/packages/vscode/src/__tests__/contributes-dev.test.ts +++ b/packages/vscode/src/__tests__/contributes-dev.test.ts @@ -104,10 +104,29 @@ describe('#1158: no "dev server" terminology on VS Code surfaces', () => { expect(offenders.map((c) => c.command)).toEqual([]); }); - it('no view id or menu when-clause references codev.devServer', () => { + it('no view id references codev.devServer', () => { const allViews = Object.values(views).flat(); expect(allViews.filter((v) => v.id.includes('devServer')).map((v) => v.id)).toEqual([]); - const wheres = titleMenus.map((m) => m.when ?? '').filter((w) => w.includes('devServer')); - expect(wheres).toEqual([]); + }); + + // Scan EVERY contributed menu group (not just view/title) and every keybinding, + // so a reintroduced devServer id / when-clause in the command palette, + // view/item/context, or a keybinding can't slip past this guard. + it('no menu entry (any group) references devServer in its command or when-clause', () => { + const allMenus = Object.values( + (PKG.contributes.menus ?? {}) as Record, + ).flat(); + const offenders = allMenus.filter( + (m) => (m.command ?? '').includes('devServer') || (m.when ?? '').includes('devServer'), + ); + expect(offenders).toEqual([]); + }); + + it('no keybinding references a devServer command', () => { + const keybindings = (PKG.contributes.keybindings ?? []) as Array<{ command?: string; when?: string }>; + const offenders = keybindings.filter( + (k) => (k.command ?? '').includes('devServer') || (k.when ?? '').includes('devServer'), + ); + expect(offenders).toEqual([]); }); }); diff --git a/packages/vscode/src/commands/dev-shared.ts b/packages/vscode/src/commands/dev-shared.ts index e13aec089..59c1e8e8a 100644 --- a/packages/vscode/src/commands/dev-shared.ts +++ b/packages/vscode/src/commands/dev-shared.ts @@ -101,7 +101,7 @@ export async function startDevForTarget( const existing = terminalManager.listDevTerminals(); const same = existing.find(d => d.builderId === target.id); if (same) { - vscode.window.showInformationMessage(`Codev: Dev server is already running for ${target.name}`); + vscode.window.showInformationMessage(`Codev: Dev is already running for ${target.name}`); await terminalManager.openDevTerminal(same.terminalId, target.id, target.name, true); return; } @@ -140,7 +140,7 @@ export async function startDevForTarget( } await terminalManager.openDevTerminal(terminal.id, target.id, target.name, true); - vscode.window.showInformationMessage(`Codev: Dev server started for ${target.name}`); + vscode.window.showInformationMessage(`Codev: Dev started for ${target.name}`); } /** @@ -248,5 +248,5 @@ export async function stopDevForTarget( } await client.killTerminal(found.terminalId); terminalManager.closeDevTerminal(targetId); - vscode.window.showInformationMessage(`Codev: Dev server stopped for ${name}`); + vscode.window.showInformationMessage(`Codev: Dev stopped for ${name}`); } diff --git a/packages/vscode/src/commands/stop-worktree-dev.ts b/packages/vscode/src/commands/stop-worktree-dev.ts index 4fa0a95e2..86b227159 100644 --- a/packages/vscode/src/commands/stop-worktree-dev.ts +++ b/packages/vscode/src/commands/stop-worktree-dev.ts @@ -34,7 +34,7 @@ export async function stopWorktreeDev( } const summary = devs.length === 1 - ? `Codev: Dev server stopped for ${devs[0]!.builderId}` + ? `Codev: Dev stopped for ${devs[0]!.builderId}` : `Codev: Stopped ${devs.length} devs`; vscode.window.showInformationMessage(summary); } diff --git a/packages/vscode/src/terminal-manager.ts b/packages/vscode/src/terminal-manager.ts index ffa23eb40..e43c01bad 100644 --- a/packages/vscode/src/terminal-manager.ts +++ b/packages/vscode/src/terminal-manager.ts @@ -477,7 +477,7 @@ export class TerminalManager { const pty = new CodevPseudoterminal(wsUrl, authKey, this.outputChannel); const position = vscode.workspace.getConfiguration('codev').get('terminalPosition', 'editor'); - // Dev servers are long-running background logs — always the bottom panel, + // Dev processes are long-running background logs — always the bottom panel, // regardless of the `codev.terminalPosition` setting (which governs the // architect/builder/shell terminals: architect → editor group 1, the // rest → group 2). diff --git a/packages/vscode/src/views/workspace.ts b/packages/vscode/src/views/workspace.ts index 31c2296a7..61abb2178 100644 --- a/packages/vscode/src/views/workspace.ts +++ b/packages/vscode/src/views/workspace.ts @@ -22,8 +22,8 @@ export class WorkspaceProvider implements vscode.TreeDataProvider this.changeEmitter.fire()); // Re-render when the dev-terminal set changes (start/stop, a swap that - // killed this workspace's dev, or cleanup) so the conditional "Stop Dev - // Server" row reflects reality across every path. + // killed this workspace's dev, or cleanup) so the conditional "Stop + // Dev" row reflects reality across every path. terminalManager.onDidChangeDevTerminals(() => this.changeEmitter.fire()); // Tower fans out a `codev-config-updated` SSE event whenever // .codev/config(.local).json changes (server-side file watcher in From ef7116c921a9079b4f604759db9b16958b9c54aa Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Mon, 13 Jul 2026 13:43:16 +0700 Subject: [PATCH 6/8] [Bugfix #1158] Thread: PR + CMAP round notes --- codev/state/bugfix-1158_thread.md | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/codev/state/bugfix-1158_thread.md b/codev/state/bugfix-1158_thread.md index f63763627..71c04a28b 100644 --- a/codev/state/bugfix-1158_thread.md +++ b/codev/state/bugfix-1158_thread.md @@ -68,3 +68,39 @@ errors were NOT from this change. **Scope note**: did NOT touch packages/vscode/CHANGELOG.md — vscode changelog is accumulated on the dedicated changelog branch by the architect after cleanup (repo convention), not in feature/bugfix PRs. Surfaced the migration note in the PR body + architect notification instead. + +## PR (phase 3) + +Two commits (fix+test landed together in the fix commit; the test file is in it) → +pushed → **PR #1173** (Fixes #1158). porch fix-phase checks passed from main checkout +(build 4.9s, tests 20.1s). Advanced to `pr` phase. CMAP 3-way (gemini/codex/claude, type pr) +running. Next: record CMAP verdicts, notify architect, `porch done` to request the `pr` gate, +then WAIT for human approval (never self-approve). + +**porch-from-where gotcha**: this project's porch state lives in the MAIN checkout's +`codev/projects/`, not the worktree. `porch status` auto-detects from the worktree, but +stateful cmds (`check`/`done`) must run from the main checkout (`cd ../.. && porch bugfix-1158`) +or they silently no-op / error "not found". + +**consult gotcha**: from this worktree, consult's project auto-detect fails ("Multiple +projects found") because the worktree's `codev/projects/` still holds all historical projects +and this one's state is in main. Disambiguate with `--issue 1158`. Also: never pipe consult to +`head` — SIGPIPE kills it before it writes `--output`. + +### CMAP outcome — REQUEST_CHANGES → fixed (commit f931aa4e) + +All 3 reviewers (gemini/codex/claude) independently caught the SAME real defect: my +first-pass verification grep `"Dev Server\|dev server"` was case-sensitive and missed the +mixed-case **"Dev server"** — so 4 user-facing toast strings (dev-shared.ts, stop-worktree-dev.ts) +still said "Dev server started/stopped/already running". Textbook "trust the protocol — CMAP +catches what solo review misses." Fixed all 4 + 2 comments + README.md (marketplace doc, ~15 +refs, command titles were mismatching the actual palette) + pir protocol.md:137 (both trees). +Strengthened the regression guard to scan ALL menu groups + keybindings. + +**Rebutted** codex's "add codev.devServer.* deprecated aliases" — the breaking rename is the +issue's explicit choice (#1158 verify #9: document the no-op, don't preserve old ids). + +Re-verified: case-insensitive grep clean (only the intentional enumeration remains); 590 unit +tests pass; compile clean. Pushed, PR body corrected (the earlier "0 hits" claim was wrong for +case-insensitive), CMAP verdicts recorded. Next: notify architect, `porch done` → request `pr` +gate, WAIT for human approval. From eb75134fb59a54aa5f548803d9c084b4de2bd368 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Mon, 13 Jul 2026 13:43:25 +0700 Subject: [PATCH 7/8] chore(porch): bugfix-1158 pr gate-requested --- .../bugfix-1158-vscode-strip-dev-server-termin/status.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml index f00062134..2be226cf4 100644 --- a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml +++ b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml @@ -7,8 +7,10 @@ current_plan_phase: null gates: pr: status: pending + requested_at: '2026-07-13T06:43:25.401Z' iteration: 1 build_complete: false history: [] started_at: '2026-07-13T06:12:19.993Z' -updated_at: '2026-07-13T06:33:47.784Z' +updated_at: '2026-07-13T06:43:25.401Z' +pr_ready_for_human: true From 189fb016d180183f56e28941c42416648cec76bb Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Mon, 13 Jul 2026 15:54:31 +0700 Subject: [PATCH 8/8] chore(porch): bugfix-1158 pr gate-approved --- .../bugfix-1158-vscode-strip-dev-server-termin/status.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml index 2be226cf4..72b711005 100644 --- a/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml +++ b/codev/projects/bugfix-1158-vscode-strip-dev-server-termin/status.yaml @@ -6,11 +6,12 @@ plan_phases: [] current_plan_phase: null gates: pr: - status: pending + status: approved requested_at: '2026-07-13T06:43:25.401Z' + approved_at: '2026-07-13T08:54:31.542Z' iteration: 1 build_complete: false history: [] started_at: '2026-07-13T06:12:19.993Z' -updated_at: '2026-07-13T06:43:25.401Z' -pr_ready_for_human: true +updated_at: '2026-07-13T08:54:31.543Z' +pr_ready_for_human: false