diff --git a/README.md b/README.md index 6d51ed2..0b26eae 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Personal [Pi](https://github.com/earendil-works/pi-mono) extensions, skills, glo - the `manage-pi-links` and `nono-profiles` project-only skills under `.pi/skills/`; - no global Pi extension symlinks. Active extensions are installed separately as pinned Gitea npm packages. -The repository contains `copy-all`, `dictate` (Linux host-service dictation), `effort-controls`, `file-search`, `interactive-subagents`, `lm-studio`, `native-hooks`, `prompt-snippets`, `subagents`, `todo-herdr`, `update`, and the private historical `workflow` extension. The link manifest does not install any extension globally. New feature work uses `develop-workflow`; the legacy extension remains unexposed as pilot evidence under [ADR 0006](docs/adr/0006-skill-led-development-workflow-04SEP2026.md). The `pptx`, `stop-slop`, `subagents`, and `xlsx` skills are intentionally excluded. Archived resources under `__archived/` are never installed. Update `config/pi-links.json` deliberately if that policy changes. +The repository contains `bash-cwd`, `copy-all`, `dictate` (Linux host-service dictation), `effort-controls`, `file-search`, `interactive-subagents`, `lm-studio`, `native-hooks`, `prompt-snippets`, `subagents`, `todo-herdr`, `update`, and the private historical `workflow` extension. The link manifest does not install any extension globally. New feature work uses `develop-workflow`; the legacy extension remains unexposed as pilot evidence under [ADR 0006](docs/adr/0006-skill-led-development-workflow-04SEP2026.md). The `pptx`, `stop-slop`, `subagents`, and `xlsx` skills are intentionally excluded. Archived resources under `__archived/` are never installed. Update `config/pi-links.json` deliberately if that policy changes. ## Fresh-machine setup @@ -132,6 +132,8 @@ The currently published and deployed extension set is: - `@jbcode/pi-interactive-subagents@3.7.3`; - `@jbcode/pi-todo-herdr@0.2.5`. +[`@jbcode/pi-bash-cwd`](extensions/bash-cwd) is an unpublished compatibility package for Pi 0.84.x. It adds a validated optional `cwd` argument to the built-in `bash` tool so commands can target hidden worktrees and nested packages without an inline `cd`. Keep using explicit directory proofs for Git worktree mutations even with the override installed. + Configure the scoped Gitea npm registry and install only the packages you want. Keep the token in the user environment or user-level npm configuration; never commit it: ```ini diff --git a/bun.lock b/bun.lock index 367fdc1..02beef8 100644 --- a/bun.lock +++ b/bun.lock @@ -18,6 +18,19 @@ "vitest": "catalog:", }, }, + "extensions/bash-cwd": { + "name": "@jbcode/pi-bash-cwd", + "version": "0.1.0", + "devDependencies": { + "@earendil-works/pi-coding-agent": "catalog:", + "typebox": "catalog:", + "typescript": "catalog:", + }, + "peerDependencies": { + "@earendil-works/pi-coding-agent": "catalog:pi-peer", + "typebox": "catalog:pi-peer", + }, + }, "extensions/copy-all": { "name": "@jbcode/pi-copy-all", "version": "0.1.0", @@ -354,6 +367,8 @@ "@ioredis/commands": ["@ioredis/commands@1.10.0", "", {}, "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q=="], + "@jbcode/pi-bash-cwd": ["@jbcode/pi-bash-cwd@workspace:extensions/bash-cwd"], + "@jbcode/pi-copy-all": ["@jbcode/pi-copy-all@workspace:extensions/copy-all"], "@jbcode/pi-dictate": ["@jbcode/pi-dictate@workspace:extensions/dictate"], diff --git a/docs/npm-packages.md b/docs/npm-packages.md index 7a79360..62f472a 100644 --- a/docs/npm-packages.md +++ b/docs/npm-packages.md @@ -57,3 +57,5 @@ pi install npm:@jbcode/pi-todo-herdr@0.2.5 ``` Pi installs runtime dependencies from the same scoped registry. `config/pi-links.json` deliberately exposes no extension symlinks, preventing duplicate local and published copies. + +`@jbcode/pi-bash-cwd` is currently source-only and is not part of the deployed release set above. It can be packed and published through the same workspace process when a Pi 0.84.x installation needs the alternate-cwd compatibility override. diff --git a/docs/todos.md b/docs/todos.md index 1dffca9..30f6edd 100644 --- a/docs/todos.md +++ b/docs/todos.md @@ -1,8 +1,8 @@ # Todos -## Honor Bash tool working directories inside hidden worktrees +## Retire the Bash cwd compatibility override after a usable Pi upgrade -During the Orca polling fix on 02SEP2026, Bash tool calls configured with `cwd` beneath `/srv/data/code/jb-pi/harness-tools/.worktrees/fix-orca-polling` ran from the primary checkout instead. A `pwd` probe reproduced the mismatch, and later install and commit commands targeted the primary checkout until they were rerun with an explicit `cd` or `git -C`. The mistaken commit was reset immediately without discarding the pre-existing working changes. Reproduce this with a disposable hidden worktree and require the tool to either honor the requested directory or fail before executing the command. Cover both workspace and nested package directories; keep explicit `cd` and `git -C` as the workaround until the regression is fixed. +Pi 0.85.0 corrects built-in tools that captured the process directory instead of using the live execution `ctx.cwd`, but it still does not declare or honor a per-call `cwd` argument. Its public `@earendil-works/pi-coding-agent` entry point also imports `@earendil-works/pi-server` without declaring that runtime dependency, so importing the package after a normal Bun install fails with `ERR_MODULE_NOT_FOUND`. Keep `@jbcode/pi-bash-cwd` until an upstream release exposes equivalent validated per-call cwd behavior and loads cleanly for extension consumers. Then verify the hidden-worktree root, nested-package, relative-path, and fail-before-execution cases against the built-in tool before removing the override package. ## Canonicalize symlinked Pi npm install roots diff --git a/docs/workflow/bash-worktree-cwd-record.md b/docs/workflow/bash-worktree-cwd-record.md index 13450a7..e9a55ae 100644 --- a/docs/workflow/bash-worktree-cwd-record.md +++ b/docs/workflow/bash-worktree-cwd-record.md @@ -3,8 +3,8 @@ ## Status - Status: active -- Current phase: 5. Implement owned slices -- Next safe action: implement and verify the approved optional `cwd` Bash argument. +- Current phase: 6. Verify the integrated worktree +- Next safe action: commit the focused implementation, then run the full repository test suite. ## Request and scope @@ -22,14 +22,14 @@ ## Acceptance criteria -- [ ] `@jbcode/pi-bash-cwd` overrides the built-in `bash` tool with one backward-compatible optional `cwd` argument while preserving the existing command, timeout, output, truncation, cancellation, session-environment, and renderer contracts. -- [ ] Absolute and relative `cwd` values resolve from the live session `ctx.cwd`; omitted `cwd` retains the session directory. -- [ ] The requested directory is validated before delegating command execution. -- [ ] A regression test executes `pwd` from both a disposable hidden worktree root and a nested workspace package directory and observes the requested directory. -- [ ] A missing requested working directory fails before the shell command can create a sentinel side effect. -- [ ] Package inventory, README guidance, and the upstream Pi 0.85.0 packaging blocker TODO are synchronized. +- [x] `@jbcode/pi-bash-cwd` overrides the built-in `bash` tool with one backward-compatible optional `cwd` argument while preserving the existing command, timeout, output, truncation, cancellation, session-environment, and renderer contracts. +- [x] Absolute and relative `cwd` values resolve from the live session `ctx.cwd`; omitted `cwd` retains the session directory. +- [x] The requested directory is validated before delegating command execution. +- [x] A regression test executes `pwd` from both a disposable hidden worktree root and a nested workspace package directory and observes the requested directory. +- [x] A missing requested working directory fails before the shell command can create a sentinel side effect. +- [x] Package inventory, README guidance, and the upstream Pi 0.85.0 packaging blocker TODO are synchronized. - [ ] Existing repository typecheck and test suites pass. -- [ ] The resolved Bash cwd TODO and temporary workaround language are removed or updated without changing unrelated historical evidence. +- [x] The resolved Bash cwd TODO and temporary workaround language are removed or updated without changing unrelated historical evidence. ## Approved implementation plan and gates @@ -45,7 +45,7 @@ | --- | --- | --- | --- | --- | --- | | Workflow setup and research | parent Pi session `01a06e08-8d07-76a7-a116-d7e3baf55b87` | 15 minutes | workflow record only | Before: clean `main` at `7e7cfdb`; after: clean feature worktree at `5f853dc` | Complete | | Initial dependency-plan implementation | parent Pi session `01a06e08-8d07-76a7-a116-d7e3baf55b87` | 15 minutes | `package.json`, `bun.lock`, focused test, workflow record | Before: clean feature worktree at `9d68d5f`; after: Pi 0.85.0 upgrade restored; focused red test retained unstaged | Paused and replanned after upstream packaging blocker | -| Local override implementation | parent Pi session `01a06e08-8d07-76a7-a116-d7e3baf55b87` | 15 minutes | `extensions/bash-cwd/**`, `scripts/bash-cwd.test.mjs` removal, `package.json`, `scripts/package-workspaces.test.mjs`, `README.md`, `docs/npm-packages.md`, `docs/todos.md`, `docs/workflow/skill-led-development-workflow-plan.md`, workflow record | Before: feature worktree at `f61f197` with inspected product changes | In progress under corrected approval | +| Local override implementation | parent Pi session `01a06e08-8d07-76a7-a116-d7e3baf55b87` | 15 minutes | `extensions/bash-cwd/**`, `scripts/bash-cwd.test.mjs` removal, `package.json`, `scripts/package-workspaces.test.mjs`, `README.md`, `docs/npm-packages.md`, `docs/todos.md`, `docs/workflow/skill-led-development-workflow-plan.md`, workflow record | Before: feature worktree at `3d68f7c` with inspected product changes; after: focused checks pass, product commit pending | Complete | ## Verification matrix @@ -53,10 +53,11 @@ | --- | --- | --- | --- | | Source/cache preflight | `git status --short --branch`; `opensrc path ...` | 0 | Clean source; Pi 0.84.4 and 0.85.0 source available locally. | | Focused cwd reproduction | inline Node harness against Pi 0.84.4 | 0 (asserted buggy outcome) | Both hidden-worktree requests observed the primary checkout; a missing requested cwd still executed a sentinel command. | -| Focused cwd regression | pending repository test | pending | pending | -| Typecheck | `bun run typecheck` | pending | pending | +| Focused cwd regression | `bun run --filter '@jbcode/pi-bash-cwd' test` | 0 | Three tests pass: explicit absolute hidden-worktree cwd, relative nested-package cwd, omitted cwd/session environment, schema compatibility, missing cwd sentinel, and missing context. | +| Package contract | `bun run test:packages`; `bun pm pack --destination /tmp --ignore-scripts --quiet` | 0 | Workspace inventory and package contents pass; package tarball created. | +| Typecheck | `bun run typecheck` | 0 | Repository TypeScript check passes. | | Full tests | `bun run test` | pending | pending | -| Fresh-process integration | pending | pending | pending | +| Fresh-process integration | focused test's delegated real Bash subprocesses | 0 | Commands execute through Pi 0.84.4's built-in Bash definition with session metadata preserved. | ## Review @@ -81,6 +82,6 @@ ## Checkpoints and blockers -- Last committed valid checkpoint: corrected-plan record commit `PENDING` +- Last committed valid checkpoint: corrected-plan approval commit `3d68f7c` - Blockers: none. -- Exact next safe action: implement the optional `cwd` schema, path preflight, and explicit-argument regression cases. +- Exact next safe action: checkpoint the focused implementation and run `bun run test`. diff --git a/docs/workflow/skill-led-development-workflow-plan.md b/docs/workflow/skill-led-development-workflow-plan.md index f36ef47..0eef7fb 100644 --- a/docs/workflow/skill-led-development-workflow-plan.md +++ b/docs/workflow/skill-led-development-workflow-plan.md @@ -100,7 +100,7 @@ Reuse rather than wrap: - `artifact-presenter`: plan and long-artifact review. - Git worktrees and normal project commands: isolation, commits, verification, rebase, and integration. -Known harness defects are workflow constraints, not footnotes. Until fixed, launch subagents directly rather than through `multi_tool_use.parallel`; never park the parent solely on an expected callback; and verify that each result was delivered. For shell work inside hidden worktrees, use explicit `cd && ...` or `git -C ...`, then verify `pwd` or Git's top-level path before mutation because the Bash tool has previously ignored its configured working directory. +Known harness defects are workflow constraints, not footnotes. Until fixed, launch subagents directly rather than through `multi_tool_use.parallel`; never park the parent solely on an expected callback; and verify that each result was delivered. `@jbcode/pi-bash-cwd` adds validated per-call Bash working directories on Pi 0.84.x. Shell mutations inside hidden worktrees still use explicit `cd && ...` or `git -C ...`, followed by `pwd` or Git top-level verification, as defense-in-depth. Before starting the full path, preflight required capabilities. Git worktree operations, a writable retained record, an explicit human interaction channel, target-interface validation when applicable, and a Git-capable independent reviewer are mandatory. Todo-herdr and artifact-presenter may degrade to the retained record and a reported artifact path, but their absence cannot bypass a gate. In print or JSON mode, or whenever a mandatory gate or validator cannot run, emit the pending decision or validation instructions and stop before product mutation. @@ -144,7 +144,7 @@ When uncertain, use the full path. Record why the light path is safe when a chan 1. Read repository instructions, relevant docs, ADRs, tests, and current Git state. 2. Record the source branch and exact base commit. 3. Create `./.worktrees/` on a descriptive feature branch before feature edits. -4. Prove every subsequent shell command's location with explicit `cd` or `git -C`; do not rely on the Bash tool's configured `cwd` until its tracked defect is fixed. +4. Prove every subsequent shell command's location with explicit `cd` or `git -C`; treat the Bash cwd override as protection against fallback execution, not a replacement for the location proof. 5. If the source checkout is dirty, explain exactly which changes the new worktree omits and ask before proceeding. 6. Atomically create the unique workflow record in the worktree and create a task tree in the session. 7. Run applicable documentation checks, then commit the initial record as a pre-mutation recovery checkpoint. diff --git a/extensions/bash-cwd/LICENSE b/extensions/bash-cwd/LICENSE new file mode 100644 index 0000000..79b4dd9 --- /dev/null +++ b/extensions/bash-cwd/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 JB + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/extensions/bash-cwd/README.md b/extensions/bash-cwd/README.md new file mode 100644 index 0000000..d50f4cd --- /dev/null +++ b/extensions/bash-cwd/README.md @@ -0,0 +1,21 @@ +# @jbcode/pi-bash-cwd + +Pi extension that adds an optional `cwd` argument to the built-in `bash` tool. Absolute paths are used directly, relative paths resolve from the Pi session directory, and omitted paths retain the session directory. The extension validates the directory before starting the command, preventing an ignored or invalid `cwd` from running in Pi's process directory. + +The override delegates execution and rendering to Pi's built-in Bash implementation. Existing `command` and `timeout` calls remain compatible. + +## Install + +```bash +pi install npm:@jbcode/pi-bash-cwd +``` + +Restart Pi or run `/reload` after installation. Pi warns that the extension replaces the built-in `bash` tool; that warning is expected. + +Use this package with Pi 0.84.x. Remove it after moving to a Pi release that honors `ctx.cwd` and can be imported by extensions without undeclared runtime dependencies. + +## Verify + +```bash +bun run --filter '@jbcode/pi-bash-cwd' test +``` diff --git a/extensions/bash-cwd/index.test.ts b/extensions/bash-cwd/index.test.ts new file mode 100644 index 0000000..e678da9 --- /dev/null +++ b/extensions/bash-cwd/index.test.ts @@ -0,0 +1,112 @@ +import assert from "node:assert/strict"; +import { execFileSync } from "node:child_process"; +import { access, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import test from "node:test"; + +import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; + +import { createContextualBashTool } from "./index.ts"; + +function git(cwd: string, ...args: string[]): void { + execFileSync("git", args, { cwd, stdio: "pipe" }); +} + +function getOutput( + result: Awaited["execute"]>>, +): string { + return result.content + .filter((item) => item.type === "text") + .map((item) => item.text) + .join("") + .trim(); +} + +async function executeIn( + sessionCwd: string, + command: string, + cwd?: string, +) { + const params = cwd === undefined ? { command } : { command, cwd }; + return createContextualBashTool().execute( + "bash-cwd-test", + params, + undefined, + undefined, + { + cwd: sessionCwd, + sessionManager: { + getSessionId: () => "bash-cwd-test-session", + getSessionFile: () => undefined, + }, + } as ExtensionContext, + ); +} + +test("bash honors hidden-worktree and nested-package cwd arguments", async (t) => { + const repository = await mkdtemp(join(tmpdir(), "pi-bash-cwd-")); + t.after(() => rm(repository, { recursive: true, force: true })); + + await writeFile(join(repository, ".gitignore"), ".worktrees/\n"); + await mkdir(join(repository, "extensions", "fixture"), { recursive: true }); + await writeFile( + join(repository, "extensions", "fixture", "package.json"), + '{"private":true}\n', + ); + + git(repository, "init", "--initial-branch=main"); + git(repository, "config", "user.name", "Bash cwd test"); + git(repository, "config", "user.email", "bash-cwd@example.invalid"); + git(repository, "add", "."); + git(repository, "commit", "-m", "fixture"); + + const worktree = join(repository, ".worktrees", "feature"); + git(repository, "worktree", "add", "-b", "feature", worktree, "main"); + const packageDirectory = join(worktree, "extensions", "fixture"); + + assert.equal(getOutput(await executeIn(repository, "pwd")), repository); + assert.equal( + getOutput(await executeIn(repository, 'printf %s "$PI_SESSION_ID"')), + "bash-cwd-test-session", + ); + assert.equal(getOutput(await executeIn(repository, "pwd", worktree)), worktree); + assert.equal( + getOutput( + await executeIn( + repository, + "pwd", + ".worktrees/feature/extensions/fixture", + ), + ), + packageDirectory, + ); + + const missingDirectory = join(worktree, "missing"); + const sentinel = join(repository, "should-not-run"); + await assert.rejects( + executeIn(repository, "touch should-not-run", missingDirectory), + /Working directory does not exist/, + ); + await assert.rejects(access(sentinel)); +}); + +test("bash exposes cwd without changing existing arguments", () => { + const schema = createContextualBashTool().parameters; + assert.deepEqual(Object.keys(schema.properties), ["command", "cwd", "timeout"]); + assert.deepEqual(schema.required, ["command"]); +}); + +test("bash fails before execution when Pi omits the tool context", async () => { + const tool = createContextualBashTool(); + await assert.rejects( + tool.execute( + "bash-cwd-test", + { command: "pwd" }, + undefined, + undefined, + undefined as unknown as ExtensionContext, + ), + /Bash execution context is unavailable/, + ); +}); diff --git a/extensions/bash-cwd/index.ts b/extensions/bash-cwd/index.ts new file mode 100644 index 0000000..c7f4084 --- /dev/null +++ b/extensions/bash-cwd/index.ts @@ -0,0 +1,89 @@ +import { stat } from "node:fs/promises"; +import { resolve } from "node:path"; + +import { + createBashToolDefinition, + type ExtensionAPI, + type ExtensionContext, +} from "@earendil-works/pi-coding-agent"; +import { type Static, Type } from "typebox"; + +const bashCwdParameters = Type.Object({ + command: Type.String({ description: "Shell command to execute" }), + cwd: Type.Optional( + Type.String({ + description: + "Working directory. Relative paths resolve from the session working directory.", + }), + ), + timeout: Type.Optional( + Type.Number({ description: "Timeout in seconds (optional, no default timeout)" }), + ), +}); + +type BashCwdInput = Static; +type BuiltInBashDefinition = ReturnType; +type BuiltInBashExecute = BuiltInBashDefinition["execute"]; + +async function resolveWorkingDirectory( + sessionCwd: string, + requestedCwd: string | undefined, +): Promise { + const cwd = resolve(sessionCwd, requestedCwd ?? "."); + + let metadata; + try { + metadata = await stat(cwd); + } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") { + throw new Error( + `Working directory does not exist: ${cwd}\nCannot execute bash commands.`, + ); + } + throw error; + } + + if (!metadata.isDirectory()) { + throw new Error( + `Working directory is not a directory: ${cwd}\nCannot execute bash commands.`, + ); + } + + return cwd; +} + +export function createContextualBashTool() { + const baseTool = createBashToolDefinition(process.cwd()); + + return { + ...baseTool, + description: + `${baseTool.description} The optional cwd may be absolute or relative to the session working directory.`, + parameters: bashCwdParameters, + async execute( + toolCallId: Parameters[0], + params: BashCwdInput, + signal: Parameters[2], + onUpdate: Parameters[3], + ctx: ExtensionContext, + ) { + if (!ctx) { + throw new Error("Bash execution context is unavailable"); + } + + const cwd = await resolveWorkingDirectory(ctx.cwd, params.cwd); + const contextualTool = createBashToolDefinition(cwd); + return contextualTool.execute( + toolCallId, + { command: params.command, timeout: params.timeout }, + signal, + onUpdate, + ctx, + ); + }, + }; +} + +export default function bashCwd(pi: ExtensionAPI): void { + pi.registerTool(createContextualBashTool()); +} diff --git a/extensions/bash-cwd/package.json b/extensions/bash-cwd/package.json new file mode 100644 index 0000000..556d3df --- /dev/null +++ b/extensions/bash-cwd/package.json @@ -0,0 +1,31 @@ +{ + "name": "@jbcode/pi-bash-cwd", + "version": "0.1.0", + "description": "Pi Bash override that honors the current tool execution working directory.", + "type": "module", + "license": "MIT", + "engines": { "node": ">=22.19.0" }, + "keywords": ["pi-package", "pi-extension"], + "files": ["index.ts", "README.md", "LICENSE"], + "pi": { "extensions": ["./index.ts"] }, + "scripts": { + "test": "node --test --experimental-strip-types index.test.ts" + }, + "peerDependencies": { + "@earendil-works/pi-coding-agent": "catalog:pi-peer", + "typebox": "catalog:pi-peer" + }, + "devDependencies": { + "@earendil-works/pi-coding-agent": "catalog:", + "typebox": "catalog:", + "typescript": "catalog:" + }, + "publishConfig": { + "registry": "https://git.jb.codes/api/packages/jb/npm/" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@git.jb.codes:7722/jb/harness-tools.git", + "directory": "extensions/bash-cwd" + } +} diff --git a/package.json b/package.json index 8238bf3..ed4449c 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "test:links": "node --test scripts/pi-links.test.mjs", "test:packages": "node --test scripts/package-workspaces.test.mjs", "test:imported": "bun run --filter '@jbcode/pi-interactive-subagents' test && bun run --filter '@jbcode/pi-native-hooks' test && bun run --filter '@jbcode/pi-todo-herdr' test", - "test:node": "node --test --experimental-strip-types extensions/dictate/index.test.ts extensions/lm-studio/index.test.ts extensions/shared/*.test.ts extensions/subagents/by-the-way.test.ts extensions/subagents/context-usage.test.ts extensions/subagents/manager.test.ts extensions/subagents/result-delivery.test.ts extensions/subagents/takeover.test.ts extensions/_workflows/*.test.ts extensions/workflow/*.test.ts", + "test:node": "node --test --experimental-strip-types extensions/bash-cwd/index.test.ts extensions/dictate/index.test.ts extensions/lm-studio/index.test.ts extensions/shared/*.test.ts extensions/subagents/by-the-way.test.ts extensions/subagents/context-usage.test.ts extensions/subagents/manager.test.ts extensions/subagents/result-delivery.test.ts extensions/subagents/takeover.test.ts extensions/_workflows/*.test.ts extensions/workflow/*.test.ts", "test:file-search": "vitest run extensions/file-search/index.spec.ts --exclude '.worktrees/**'", "test:live": "node --test --experimental-strip-types extensions/subagents/claude.test.ts extensions/subagents/codex.test.ts" }, diff --git a/scripts/package-workspaces.test.mjs b/scripts/package-workspaces.test.mjs index ea023a2..63dfadf 100644 --- a/scripts/package-workspaces.test.mjs +++ b/scripts/package-workspaces.test.mjs @@ -10,6 +10,7 @@ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const extensionsRoot = path.join(root, "extensions"); const registry = "https://git.jb.codes/api/packages/jb/npm/"; const expectedWorkspaces = [ + "bash-cwd", "copy-all", "dictate", "effort-controls",