Skip to content

Commit c367d30

Browse files
committed
Merge branch 'main' into dev
2 parents 7154322 + 1cbf0b2 commit c367d30

2 files changed

Lines changed: 100 additions & 13 deletions

File tree

scripts/test-sandbox-skills.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Debug script: provisions a bare sandbox, installs skills globally, and dumps the results.
3+
* Uses Vercel OIDC for sandbox auth — no repo needed.
4+
*
5+
* Usage:
6+
* npx tsx scripts/test-sandbox-skills.ts
7+
*/
8+
9+
import { Sandbox } from "@vercel/sandbox";
10+
11+
const INJECTED_SKILLS = [
12+
{ repo: "https://github.com/obra/superpowers", skill: "using-superpowers" },
13+
{ repo: "https://github.com/obra/superpowers", skill: "requesting-code-review" },
14+
{ repo: "https://github.com/anthropics/skills", skill: "frontend-design" },
15+
];
16+
17+
async function main() {
18+
console.log("\n=== Provisioning sandbox ===\n");
19+
20+
const sandbox = await Sandbox.create({
21+
runtime: "node24",
22+
timeout: 300_000,
23+
});
24+
25+
console.log("Sandbox created.\n");
26+
27+
await sandbox.runCommand("bash", ["-c", "git init && git commit --allow-empty -m 'init'"]);
28+
29+
console.log("=== Installing Claude Code ===");
30+
const installCC = await sandbox.runCommand("npm", [
31+
"install",
32+
"-g",
33+
"@anthropic-ai/claude-code",
34+
]);
35+
console.log("stdout:", (await installCC.stdout()).slice(-200));
36+
console.log("stderr:", (await installCC.stderr()).slice(-200));
37+
38+
for (const { repo, skill } of INJECTED_SKILLS) {
39+
console.log(`\n=== Installing skill globally: ${skill} ===`);
40+
const result = await sandbox.runCommand("npx", [
41+
"-y", "skills", "add", repo, "--skill", skill, "--yes", "-g",
42+
]);
43+
console.log("stdout:", (await result.stdout()).slice(-300) || "(empty)");
44+
console.log("stderr:", (await result.stderr()).slice(-300) || "(empty)");
45+
}
46+
47+
console.log("\n=== .claude/skills/ (project) ===");
48+
const projectSkills = await sandbox.runCommand("bash", [
49+
"-c",
50+
"ls -laR .claude/skills/ 2>/dev/null || echo '(directory does not exist)'",
51+
]);
52+
console.log(await projectSkills.stdout());
53+
54+
console.log("=== skills-lock.json (project) ===");
55+
const lock = await sandbox.runCommand("bash", [
56+
"-c",
57+
"cat skills-lock.json 2>/dev/null || echo '(file does not exist)'",
58+
]);
59+
console.log(await lock.stdout());
60+
61+
console.log("=== ~/.claude/skills/ (global) ===");
62+
const globalSkills = await sandbox.runCommand("bash", [
63+
"-c",
64+
"ls -laR ~/.claude/skills/ 2>/dev/null || echo '(directory does not exist)'",
65+
]);
66+
console.log(await globalSkills.stdout());
67+
68+
console.log("=== Find all SKILL.md files (everywhere) ===");
69+
const skillFiles = await sandbox.runCommand("bash", [
70+
"-c",
71+
"find / -name 'SKILL.md' -not -path '*/node_modules/*' 2>/dev/null || echo '(none found)'",
72+
]);
73+
console.log(await skillFiles.stdout());
74+
75+
console.log("\n=== Stopping sandbox ===");
76+
await sandbox.stop();
77+
console.log("Done.");
78+
}
79+
80+
main().catch((err) => {
81+
console.error("Fatal:", err);
82+
process.exit(1);
83+
});

src/lib/dispatch.test.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,11 @@ describe("dispatchTicket", () => {
119119

120120
it("dispatches review-fix workflow when PR exists", async () => {
121121
const adapters = makeAdapters({
122-
findPR: vi
123-
.fn()
124-
.mockResolvedValue({
125-
id: 7,
126-
url: "https://github.com/pr/7",
127-
branch: "blazebot/proj-42",
128-
}),
122+
findPR: vi.fn().mockResolvedValue({
123+
id: 7,
124+
url: "https://github.com/pr/7",
125+
branch: "blazebot/proj-42",
126+
}),
129127
});
130128
const { dispatchTicket } = await import("./dispatch.js");
131129

@@ -196,12 +194,18 @@ describe("dispatchTicket", () => {
196194

197195
it("only one concurrent dispatch wins when claim is atomic", async () => {
198196
let claimed = false;
199-
const claim = vi.fn().mockImplementation(async (_key: string, value: string) => {
200-
if (claimed) return false;
201-
claimed = true;
202-
return true;
203-
});
204-
const getRunId = vi.fn().mockImplementation(async () => (claimed ? `claiming:${Date.now()}` : null));
197+
const claim = vi
198+
.fn()
199+
.mockImplementation(async (_key: string, value: string) => {
200+
if (claimed) return false;
201+
claimed = true;
202+
return true;
203+
});
204+
const getRunId = vi
205+
.fn()
206+
.mockImplementation(async () =>
207+
claimed ? `claiming:${Date.now()}` : null,
208+
);
205209

206210
const makeAdaptersForRace = () => makeAdapters({ claim, getRunId });
207211
const { dispatchTicket } = await import("./dispatch.js");

0 commit comments

Comments
 (0)