Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions docs/beta-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Beta test — buddy playbook

polycode is a **terminal** coding agent (not a website). Your buddy runs it on their
machine, or sits at yours. Results of automated checks + a fill-in checklist are logged
**locally** under `.polycode/beta-logs/` (gitignored — never committed, no API keys).

## You (host)

From the repo:

```powershell
corepack pnpm -C "C:\Users\gasan\OneDrive\Dev\Projects\polycode" install
corepack pnpm -C "C:\Users\gasan\OneDrive\Dev\Projects\polycode" beta -- --tester you
```

That runs typecheck + the unit suite and writes two local files (gitignored):

- `.polycode/beta-logs/<timestamp>_you.md`
- `.polycode/beta-logs/LATEST.md` (last **automated** run — send this one; checklist-only does not overwrite it)

Live model round-trip (needs a Grok key already saved):

```powershell
corepack pnpm -C "C:\Users\gasan\OneDrive\Dev\Projects\polycode" beta -- --tester you --smoke xai:grok-4.3
```

Checklist-only (no test run — just a blank log for a session):

```powershell
corepack pnpm -C "C:\Users\gasan\OneDrive\Dev\Projects\polycode" beta -- --tester buddy --checklist-only
```

Send your buddy **that markdown file** after they fill the checkboxes. Not `.env`, not the keychain.

## Your buddy (first 10 minutes)

1. Node 20+ installed.
2. In the repo:

```powershell
corepack pnpm install
corepack pnpm dev
```

3. Settings: arrow to **xAI (Grok)** (not Meta Muse). Enter → paste `xai-…` key → Enter.
Chat should open. If stuck, they have a Grok key in `.env` as `XAI_API_KEY=` or `GROK_API_KEY=` and press **i**.
4. Work through the checklist in the log file (or below). Mark pass/fail. No keys in notes.
5. Quit with `/exit`.

### What to try

| Try | Expect |
|---|---|
| `/help` | Overlay of commands, Esc closes |
| `/mo` + Tab | Completes toward `/mode` or `/model` |
| “what is this repo?” | Tools run; answer mentions polycode |
| `/mode plan` then “edit README” | Writes refused |
| `/mode ask` then a tiny edit | `y` / `a` / `n` prompt |
| `/team add a comment in README` | Explorers, then a worktree implement (git repo) |
| `/dashboard` | Child list; Enter peek; `a` attach |
| Long turn + **Ctrl+B** | Composer comes back; kids still in dashboard |
| `/loop 15s say ping` | Recurring line; `/loop stop` ends it |
| `/hepl` | Error “did you mean /help?” — not sent to Grok |

## Safety for a buddy on your box

- Use **ask** mode (`/mode ask`), not yolo.
- They should not need `--serve` (hosted HTTP).
- Their key: they paste their own Grok key, or you temporarily set one and `/settings` when they leave.
- Logs in `.polycode/beta-logs/` are local only.

## After the session

```powershell
corepack pnpm beta -- --tester buddy-name --checklist-only
```

Fill the checklist in the new file, keep it in `.polycode/beta-logs/`, and tell you what failed.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"dev": "tsx packages/cli/src/index.ts",
"serve": "tsx packages/cli/src/index.ts --serve",
"smoke": "tsx scripts/smoke.ts",
"beta": "tsx scripts/beta-log.ts",
"route-check": "tsx scripts/route-check.ts",
"test": "vitest run",
"test:watch": "vitest",
Expand Down
42 changes: 42 additions & 0 deletions packages/core/src/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,48 @@ describe("Agent", () => {
expect(agent.history()).toHaveLength(0);
});

it("stamps worktree isolation on tool_call before the UI sees the call", async () => {
const task: ToolSpec = {
name: "task",
description: "task",
parameters: {},
permission: "mutating",
parallelSafe: false,
async run(input: { description: string; prompt: string }, ctx) {
if (!ctx.spawnChild) return { output: "no spawn", isError: true };
return ctx.spawnChild({ ...input, subagent_type: "general" });
},
};
const provider = new ScriptedProvider([
[
{
type: "tool_call",
call: { type: "tool_call", id: "1", name: "task", input: { description: "a", prompt: "a" } },
},
{
type: "tool_call",
call: { type: "tool_call", id: "2", name: "task", input: { description: "b", prompt: "b" } },
},
{ type: "stop", reason: "tool_use" },
],
[{ type: "text_delta", text: "ca" }, { type: "stop", reason: "end_turn" }],
[{ type: "text_delta", text: "cb" }, { type: "stop", reason: "end_turn" }],
[{ type: "text_delta", text: "parent" }, { type: "stop", reason: "end_turn" }],
]);
const agent = new Agent(provider, [task], new PermissionEngine("yolo", async () => "once"), {
sandbox,
openWorktree: async () => ({ sandbox, path: "/tmp/wt-stamp" }),
});
agent.pushUser("go");
const events = await collect(agent);
const calls = events.filter((e) => e.type === "tool_call");
expect(calls).toHaveLength(2);
for (const ev of calls) {
if (ev.type !== "tool_call") continue;
expect((ev.call.input as { isolation?: string }).isolation).toBe("worktree");
}
});

it("records worktree paths from spawnChild", async () => {
const provider = new ScriptedProvider([
[{ type: "text_delta", text: "ok" }, { type: "stop", reason: "end_turn" }],
Expand Down
Loading
Loading