mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 19:28:46 +01:00
test(claude): bind skills fixtures to explicit runner behavior
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
9708571b43
commit
804a38a4e1
4 files changed
+50
-13
No files matched your search
@@ -399,3 +399,21 @@ port has a listener but current API health did not respond, so its current polic
|
||||
state is unconfirmed rather than asserted stopped or reverified. No accounting
|
||||
hold was cleared by this audit. Timer heartbeats and automatic paid retries remain
|
||||
disabled. No local Docker or Rust builds occurred.
|
||||
|
||||
|
||||
## Complete CI fixture corrections — 2026-10-12
|
||||
|
||||
The first current-head matrix exposed stale fixture assumptions after graduation:
|
||||
experimental harness-switch rejection still targeted Claude, Linux SSH creation
|
||||
still expected Legacy, and Legacy instruction/skill cases relied on an implicit
|
||||
runner. The gating case now uses Pi; all 56 validation-route controls pass.
|
||||
Qualified SSH creation asserts native Claude/Opus 5.5; all 92 permission-route
|
||||
controls pass. Legacy instruction/skill fixtures explicitly choose Legacy.
|
||||
The native Claude creation/hire matrix now checks preserved skill-version pins
|
||||
and CEO defaults, while omitting the legacy operational skill supplied by PRP.
|
||||
All 111 skills-route controls pass. Builder/config controls retain the shared
|
||||
package and mounted-form evidence rather than a duplicate UI pure-function test
|
||||
that expected blank effort to restore saved values. The historical missing-form
|
||||
fixture now deletes the property instead of assigning an invalid typed undefined;
|
||||
Codex package noemit passes. These corrections make no provider calls and change
|
||||
no runtime artifact identities.
|
||||
@@ -121,7 +121,9 @@ describe("buildPaperclipRunnerConfig", () => {
|
||||
it.each(["codex", "claude"])("preserves, overrides and explicitly clears saved %s reasoning effort", harness => {
|
||||
const profile = harness === "codex" ? { provider: "codex" } : { provider: "acpx", acpxAgent: "claude" };
|
||||
const values = makeValues({ adapterSchemaValues: { ...profile, modelReasoningEffort: "high", reasoningEffort: "low", effort: "low" } });
|
||||
expect(buildPaperclipRunnerConfig({ ...values, thinkingEffort: undefined }).modelReasoningEffort).toBe("high");
|
||||
const unhydrated = { ...values };
|
||||
Reflect.deleteProperty(unhydrated, "thinkingEffort");
|
||||
expect(buildPaperclipRunnerConfig(unhydrated).modelReasoningEffort).toBe("high");
|
||||
expect(buildPaperclipRunnerConfig({ ...values, thinkingEffort: "max" }).modelReasoningEffort).toBe("max");
|
||||
const cleared = buildPaperclipRunnerConfig({ ...values, thinkingEffort: "" });
|
||||
for (const key of ["modelReasoningEffort", "reasoningEffort", "effort"]) expect(cleared).not.toHaveProperty(key);
|
||||
|
||||
@@ -1005,6 +1005,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
desiredSkills: ["paperclip"],
|
||||
adapterConfig: {},
|
||||
}));
|
||||
@@ -1038,6 +1039,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
desiredSkills: [{
|
||||
key: "paperclipai/paperclip/paperclip",
|
||||
versionId: "22222222-2222-4222-8222-222222222222",
|
||||
@@ -1057,6 +1059,7 @@ describe("agent skill routes", () => {
|
||||
name: "Security Engineer",
|
||||
role: "security",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {},
|
||||
}));
|
||||
|
||||
@@ -1088,6 +1091,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {},
|
||||
instructionsBundle: {
|
||||
files: {
|
||||
@@ -1124,6 +1128,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {
|
||||
instructionsFilePath: "/tmp/existing/AGENTS.md",
|
||||
promptTemplate: "You are QA.",
|
||||
@@ -1150,6 +1155,7 @@ describe("agent skill routes", () => {
|
||||
name: "CEO",
|
||||
role: "ceo",
|
||||
adapterType,
|
||||
...(adapterType === "claude_local" ? { runner: "legacy" } : {}),
|
||||
adapterConfig: adapterType === "paperclip_runner" ? { provider: "codex" } : {},
|
||||
}));
|
||||
|
||||
@@ -1180,6 +1186,7 @@ describe("agent skill routes", () => {
|
||||
name: "Research Lead",
|
||||
role: "ceo",
|
||||
adapterType,
|
||||
...(adapterType === "claude_local" ? { runner: "legacy" } : {}),
|
||||
adapterConfig: adapterType === "paperclip_runner" ? { provider: "codex" } : {},
|
||||
instructionsBundle: { entryFile: "AGENTS.md", files: customFiles },
|
||||
}));
|
||||
@@ -1206,6 +1213,7 @@ describe("agent skill routes", () => {
|
||||
name: "Engineer",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {},
|
||||
}));
|
||||
|
||||
@@ -1233,6 +1241,7 @@ describe("agent skill routes", () => {
|
||||
name: "Ada",
|
||||
role: "general",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {},
|
||||
onboardingFirstAgent: true,
|
||||
}));
|
||||
@@ -1264,7 +1273,12 @@ describe("agent skill routes", () => {
|
||||
{ adapterType: "codex_local", runner: "legacy", platform: "darwin", expectedType: "codex_local" },
|
||||
{ adapterType: "codex_local", runner: "auto", platform: "win32", expectedType: "codex_local" },
|
||||
];
|
||||
it.each([...codexRunnerCases, { adapterType: "claude_local", runner: "auto", platform: "linux", expectedType: "claude_local" }].flatMap((runnerCase) => [
|
||||
const creationRunnerCases = [...codexRunnerCases,
|
||||
{ adapterType: "claude_local", runner: "auto", platform: "linux", expectedType: "claude_local" },
|
||||
{ adapterType: "claude_local", runner: "auto", platform: "darwin", expectedType: "paperclip_runner" },
|
||||
{ adapterType: "claude_local", runner: "legacy", platform: "darwin", expectedType: "claude_local" },
|
||||
];
|
||||
it.each(creationRunnerCases.flatMap((runnerCase) => [
|
||||
["agents", "paperclipai/paperclip/paperclip-create-agent"],
|
||||
["agent-hires", "paperclipai/paperclip/paperclip-create-agent"],
|
||||
["agents", "paperclip"],
|
||||
@@ -1288,7 +1302,7 @@ describe("agent skill routes", () => {
|
||||
expect(input.role).toBe("general");
|
||||
expect(input.adapterType).toBe(expectedType);
|
||||
const native = expectedType === "paperclip_runner";
|
||||
if (native) expect(input.adapterConfig.provider).toBe("codex");
|
||||
if (native) expect(input.adapterConfig).toMatchObject(adapterType === "claude_local" ? { provider: "acpx", acpxAgent: "claude", model: "claude-opus-5-5" } : { provider: "codex" });
|
||||
const canonicalKey = skill === "paperclip" ? "paperclipai/paperclip/paperclip" : skill;
|
||||
const expected = ["paperclip", "paperclip-board", "paperclip-converting-plans-to-tasks", "paperclip-create-agent", "para-memory-files", "first-task"]
|
||||
// Native PRP supplies the operational contract; role skills and their pins remain assigned.
|
||||
@@ -1308,17 +1322,17 @@ describe("agent skill routes", () => {
|
||||
expect(mockAgentService.create.mock.calls[0][1].adapterConfig.paperclipSkillSync).toBeUndefined();
|
||||
});
|
||||
|
||||
it.each(codexRunnerCases.flatMap((runnerCase) => ["agents", "agent-hires"].map((route) => ({ ...runnerCase, route }))))("assigns core skills without first-task to ordinary CEOs via $route using $runner on $platform", async ({ route, runner, platform, expectedType }) => {
|
||||
it.each(creationRunnerCases.flatMap((runnerCase) => ["agents", "agent-hires"].map((route) => ({ ...runnerCase, route }))))("assigns core skills without first-task to ordinary CEOs via $route using $runner on $platform", async ({ route, runner, platform, expectedType, adapterType }) => {
|
||||
runnerTarget.platform = platform;
|
||||
runnerTarget.architecture = platform === "darwin" ? "arm64" : "x64";
|
||||
const res = await request(await createApp())
|
||||
.post(`/api/companies/company-1/${route}`)
|
||||
.send({ name: "CEO", role: "ceo", adapterType: "codex_local", ...(runner === "auto" ? {} : { runner }) });
|
||||
.send({ name: "CEO", role: "ceo", adapterType, ...(runner === "auto" ? {} : { runner }) });
|
||||
expect(res.status, JSON.stringify(res.body)).toBe(201);
|
||||
const input = mockAgentService.create.mock.calls[0][1];
|
||||
expect(input.adapterType).toBe(expectedType);
|
||||
const native = expectedType === "paperclip_runner";
|
||||
if (native) expect(input.adapterConfig.provider).toBe("codex");
|
||||
if (native) expect(input.adapterConfig).toMatchObject(adapterType === "claude_local" ? { provider: "acpx", acpxAgent: "claude", model: "claude-opus-5-5" } : { provider: "codex" });
|
||||
const desiredSkills = input.adapterConfig.paperclipSkillSync.desiredSkills;
|
||||
const expected = ["paperclip", "paperclip-board", "paperclip-converting-plans-to-tasks", "paperclip-create-agent", "para-memory-files"]
|
||||
.filter((name) => !native || name !== "paperclip")
|
||||
@@ -1334,7 +1348,8 @@ describe("agent skill routes", () => {
|
||||
type: "agent", agentId: "11111111-1111-4111-8111-111111111111", companyId: "company-1",
|
||||
}))
|
||||
.post("/api/companies/company-1/agent-hires")
|
||||
.send({ name: "Biff", role: "general", adapterType: "claude_local", onboardingFirstAgent: true });
|
||||
.send({ name: "Biff", role: "general", adapterType: "claude_local",
|
||||
runner: "legacy", onboardingFirstAgent: true });
|
||||
expect(res.status, JSON.stringify(res.body)).toBe(201);
|
||||
expect(mockAgentService.create.mock.calls[0][1].adapterConfig.paperclipSkillSync).toBeUndefined();
|
||||
await vi.waitFor(() => expect(mockAgentInstructionsService.materializeManagedBundle).toHaveBeenCalled());
|
||||
@@ -1371,6 +1386,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
desiredSkills: ["paperclip"],
|
||||
adapterConfig: {},
|
||||
});
|
||||
@@ -1396,6 +1412,7 @@ describe("agent skill routes", () => {
|
||||
name: "First Lead",
|
||||
role: "ceo",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {},
|
||||
});
|
||||
|
||||
@@ -1453,6 +1470,7 @@ describe("agent skill routes", () => {
|
||||
name: "First Lead",
|
||||
role: "ceo",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
desiredSkills: ["paperclip"],
|
||||
adapterConfig: {},
|
||||
});
|
||||
@@ -1474,6 +1492,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {},
|
||||
});
|
||||
|
||||
@@ -1491,6 +1510,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
desiredSkills: [{
|
||||
key: "paperclipai/paperclip/paperclip",
|
||||
versionId: "22222222-2222-4222-8222-222222222222",
|
||||
@@ -1515,6 +1535,7 @@ describe("agent skill routes", () => {
|
||||
role: "engineer",
|
||||
icon: "crown",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
desiredSkills: ["paperclip"],
|
||||
adapterConfig: {},
|
||||
sourceIssueId,
|
||||
@@ -1569,6 +1590,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {},
|
||||
instructionsBundle: {
|
||||
files: {
|
||||
@@ -1605,6 +1627,7 @@ describe("agent skill routes", () => {
|
||||
name: "QA Agent",
|
||||
role: "engineer",
|
||||
adapterType: "claude_local",
|
||||
runner: "legacy",
|
||||
adapterConfig: {
|
||||
instructionsFilePath: "/tmp/existing/AGENTS.md",
|
||||
promptTemplate: "You are QA.",
|
||||
|
||||
@@ -12,7 +12,6 @@ import { CodexLocalConfigFields } from "./config-fields";
|
||||
import { buildCodexRunnerConfig } from "./config-fields";
|
||||
import { defaultCreateValues } from "@/components/agent-config-defaults";
|
||||
import { resolveCodexLocalCliPolicy } from "@paperclipai/adapter-codex-local";
|
||||
import { buildPaperclipRunnerConfig } from "@paperclipai/adapter-codex-local/ui";
|
||||
|
||||
beforeAll(() => { Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true }); });
|
||||
|
||||
@@ -55,11 +54,6 @@ async function renderRunner(config: Record<string, unknown>, expand?: string, in
|
||||
}
|
||||
|
||||
describe("Paperclip Runner Codex configuration", () => {
|
||||
it.each(["", "max"])("preserves or overrides saved native Codex reasoning effort (%s)", thinkingEffort => {
|
||||
const values = { ...defaultCreateValues, thinkingEffort, adapterSchemaValues: { provider: "codex", modelReasoningEffort: "high" } };
|
||||
expect(buildPaperclipRunnerConfig(values).modelReasoningEffort).toBe(thinkingEffort || "high");
|
||||
expect(buildPaperclipRunnerConfig({ ...values, adapterSchemaValues: { provider: "acpx", acpxAgent: "claude", modelReasoningEffort: "high" } })).not.toHaveProperty("modelReasoningEffort");
|
||||
});
|
||||
it.each(["", "--sandbox,read-only"])("shows actual automatic Legacy policy and preserves the explicit toggle (%s)", async (extraArgs) => {
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
|
||||
Reference in new issue
Block a user