Skip to content

Commit 5a032b9

Browse files
committed
require team visibility for context loops
1 parent 2f8c3fc commit 5a032b9

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { describe, expect, it } from "vitest";
2+
import { buildLoopBuilderPrompt } from "./loopBuilderPrompt";
3+
4+
describe("buildLoopBuilderPrompt", () => {
5+
it("embeds the seed instructions when provided", () => {
6+
const prompt = buildLoopBuilderPrompt({
7+
instructions: "Summarize failing CI runs",
8+
});
9+
expect(prompt).toContain(
10+
"Here's what I want automated:\n\nSummarize failing CI runs",
11+
);
12+
expect(prompt).not.toContain("Start by asking me");
13+
});
14+
15+
it.each([
16+
{ name: "absent", instructions: undefined },
17+
{ name: "whitespace-only", instructions: " \n" },
18+
])("asks for ideas when instructions are $name", ({ instructions }) => {
19+
const prompt = buildLoopBuilderPrompt({ instructions });
20+
expect(prompt).toContain("Start by asking me what I want automated");
21+
expect(prompt).not.toContain("Here's what I want automated");
22+
});
23+
24+
it("includes the context target block with folder id and team visibility", () => {
25+
const prompt = buildLoopBuilderPrompt({
26+
context: { folderId: "folder-9", name: "growth" },
27+
});
28+
expect(prompt).toContain('the context "#growth"');
29+
expect(prompt).toContain(
30+
'{"folder_id": "folder-9", "name": "growth", "outputs": {"post_to_feed": true}}',
31+
);
32+
expect(prompt).toContain("Make it a team loop");
33+
expect(prompt).not.toContain("Keep it a personal loop");
34+
});
35+
36+
it("omits the context block when no context is given", () => {
37+
expect(buildLoopBuilderPrompt({})).not.toContain("context_target");
38+
});
39+
});

packages/ui/src/features/loops/loopBuilderPrompt.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ ${
2323
: `Start by asking me what I want automated, and offer a couple of concrete ideas.\n`
2424
}${
2525
context
26-
? `This loop is being created for the context "#${context.name}". In the config you assemble, set \`context_target\` to {"folder_id": "${context.folderId}", "name": "${context.name}", "outputs": {"post_to_feed": true}} so its runs post to that context's feed. Keep it a personal loop.\n\n`
26+
? `This loop is being created for the context "#${context.name}". In the config you assemble, set \`context_target\` to {"folder_id": "${context.folderId}", "name": "${context.name}", "outputs": {"post_to_feed": true}} so its runs post to that context's feed. Make it a team loop: context-attached loops post to a shared feed, so the backend rejects them as personal.\n\n`
2727
: ""
2828
}How to build it:
2929
@@ -35,7 +35,7 @@ ${
3535
- Whether it may open pull requests, and how I want to hear about runs (in-app, email, or Slack).
3636
- A short name.
3737
4. If the loop works on a repository, resolve its GitHub integration by calling \`integrations-list\` for THIS project and use that integration's real \`github_integration_id\`. Never invent or reuse an id from memory. If this project has no GitHub integration, do NOT attach a repository or guess an id: tell me to connect GitHub for this project first, or build a report-only loop if that fits what I asked for.
38-
5. As soon as you have a working draft and the essentials, call the PostHog MCP \`loops-review\` tool with the full assembled configuration (the same fields \`loops-create\` takes: name, instructions, runtime_adapter, triggers, behaviors, notifications, and so on). Make it a personal loop unless I ask otherwise.
38+
5. As soon as you have a working draft and the essentials, call the PostHog MCP \`loops-review\` tool with the full assembled configuration (the same fields \`loops-create\` takes: name, instructions, runtime_adapter, triggers, behaviors, notifications, and so on). Unless a context or I say otherwise, make it a personal loop.
3939
4040
The \`loops-review\` card IS the review surface: it renders the whole loop for me to read and gives me a Create button. Do NOT review the loop as plain text. Never paste the drafted config into a message and ask "does this look right?", and never just narrate that it's ready and stop. The moment you have enough, call \`loops-review\`. If I ask for changes, call \`loops-review\` again with the updated config. Never call \`loops-create\` yourself: the card's Create button creates the loop once I confirm.`;
4141
}

0 commit comments

Comments
 (0)