mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
Keep one VM per environment with independent lease cgroups, persistent workspaces, immutable runner images, and an explicit experimental gate. Add live compatibility, recovery, browser-preview, and stress campaigns. Co-Authored-By: Paperclip <noreply@paperclip.ing>
86 lines
3.8 KiB
TypeScript
86 lines
3.8 KiB
TypeScript
import type { RunnerTaskFixture } from "./types.js";
|
|
|
|
export const FIRST_TASK_CASES = [
|
|
["interview-first-response", "Interview: first response", "interview", 1],
|
|
["clear-task-first-response", "Clear task: first response", "task", 1],
|
|
[
|
|
"ambiguous-task-first-response",
|
|
"Ambiguous task: first response",
|
|
"ambiguous",
|
|
1,
|
|
],
|
|
[
|
|
"plain-message-first-response",
|
|
"Opening card replaced by a message",
|
|
"message",
|
|
1,
|
|
],
|
|
["plan-first-response", "Explicit plan: first response", "plan", 1],
|
|
[
|
|
"ordinary-task-control",
|
|
"Other tasks do not inherit onboarding policy",
|
|
"ordinary",
|
|
1,
|
|
],
|
|
["interview-plan-accept", "Interview, plan, and acceptance", "interview", 3],
|
|
["task-card-accept", "Subtask accepted through a card", "task", 3],
|
|
["accept-while-running", "Accept a proposal while its agent is still running", "task", 3],
|
|
["task-reply-accept", "Subtask accepted in conversation", "task", 3],
|
|
[
|
|
"clarify-propose-accept",
|
|
"Clarification, proposal, and acceptance",
|
|
"ambiguous",
|
|
4,
|
|
],
|
|
["revise-accept", "Revise scope before accepting", "task", 4],
|
|
["reject-no-execution", "Decline proposed work", "task", 2],
|
|
] as const;
|
|
export type FirstTaskCaseId = (typeof FIRST_TASK_CASES)[number][0];
|
|
export type FirstTaskOpening = (typeof FIRST_TASK_CASES)[number][2];
|
|
export const firstTaskMarker = (nonce: string) =>
|
|
`GARDEN${nonce.replace(/[^a-z0-9]/gi, "")}`;
|
|
export function firstTaskScenario(id: string, nonce: string) {
|
|
const entry = FIRST_TASK_CASES.find((row) => row[0] === id);
|
|
if (!entry) throw new Error(`Unknown first-task case ${id}`);
|
|
const marker = firstTaskMarker(nonce);
|
|
const originalMarker = id === "revise-accept" ? `DRAFT${marker}` : marker;
|
|
const task = `I need a two-sentence welcome note for our neighborhood garden club. It should invite beginners to our free Saturday meetup and include the phrase ${originalMarker}. Save the finished note as a document attached to the task.`;
|
|
const facts = `We run a neighborhood garden club for beginners. Our first goal is a two-sentence welcome note inviting people to our free Saturday meetup. We have no budget and need no outside tools. Done means the note is saved as a task document and includes ${marker}.`;
|
|
return {
|
|
id: entry[0],
|
|
opening: entry[2],
|
|
marker,
|
|
originalMarker,
|
|
facts,
|
|
firstResponseOnly:
|
|
id.endsWith("first-response") || id === "ordinary-task-control",
|
|
prompt:
|
|
entry[2] === "ambiguous"
|
|
? "Help me get my organization going."
|
|
: entry[2] === "plan"
|
|
? `Write a short plan for welcoming new members to our garden club. ${facts} Let me review the plan before any work starts.`
|
|
: entry[2] === "ordinary"
|
|
? `Write the welcome note now on this task; no interview or subtask is needed. ${task}`
|
|
: task,
|
|
revision: `Change the note: invite people to our Sunday meetup instead, and replace ${originalMarker} with ${marker}. Please revise your proposal; I have not accepted it yet.`,
|
|
acceptance: "Yes, I accept that proposal. Please do it.",
|
|
rejection:
|
|
"No, do not proceed. I do not want this work done. Please acknowledge that and stop.",
|
|
};
|
|
}
|
|
export const firstTaskTasks: readonly RunnerTaskFixture[] =
|
|
FIRST_TASK_CASES.map(([id, label, , expectedRunCount]) => ({
|
|
id,
|
|
label,
|
|
groups: ["onboarding"],
|
|
flow: "first_task",
|
|
workMode: "standard",
|
|
expectedRunCount,
|
|
attemptTimeoutMs: { local: 15 * 60_000, daytona: 15 * 60_000, "exe-dev": 15 * 60_000 },
|
|
expectedTerminalState: { issue: "in_review", run: "succeeded" },
|
|
buildTitle: (nonce) => `First task ${id} ${nonce}`,
|
|
buildPrompt: (nonce) => firstTaskScenario(id, nonce).prompt,
|
|
buildVisibleMarker: firstTaskMarker,
|
|
buildMatchers: () => [], // Checkpoints and state effects are graded by first-task-scoring.
|
|
}));
|