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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ it does). The persona compiles to `persona.json`; deploy with

| Agent | Fires on | What it does |
| --- | --- | --- |
| [**cloud-team-implementer**](cloud-team-implementer/) | launched by a teamSolve lead roster | Implements the assigned issue in its own sandbox and opens one focused pull request. |
| [**cloud-team-reviewer**](cloud-team-reviewer/) | launched by a teamSolve lead roster | Reviews a teammate's branch against the issue spec and returns verifiable, actionable findings. |
| [**granola**](granola/) | a new Granola note (Nango sync → `file.created`) | Detects prospect calls, files a Linear issue with the ask, and opens a GitHub PR implementing it. |
| [**hn-monitor**](hn-monitor/) | schedule (2×/day) | Scans Hacker News for your topics and posts a digest to Slack. |
| [**linear**](linear/) | Linear `issue.create` (labelled) / `comment.create` | Implements the issue and opens a GitHub PR; comments the PR link back. |
Expand Down
48 changes: 48 additions & 0 deletions cloud-team-implementer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Cloud Team Implementer
======================

The implementation member of a teamSolve roster. When a team lead's trigger
fires (for example an issue labeled `team`), the cloud team dispatcher launches
each roster member into its own sandbox — this persona is what steers the
implementation member: codex harness, high reasoning, and a working agreement
tuned for turning an issue spec into one focused branch and pull request.

How it runs
-----------

This persona is **launched by a team lead, never by events**. It declares no
triggers and no schedules; deploying it simply makes the slug available for a
`team.json` roster to reference (roster binding fails closed if a member slug
is not deployed). The handler only logs a warning if cloud ever routes an
event to it directly.

What the member does on launch
------------------------------

1. Reads the assigned issue spec and the surrounding code.
2. Implements the smallest complete change that satisfies the spec — adjacent
problems are noted in the PR body, not fixed.
3. Writes or updates tests that pin the changed behavior.
4. Runs the repository's checks and reports their real results.
5. Opens exactly one branch and one pull request, with assumptions and
verification steps recorded in the body.

Deploy
------

```bash
agentworkforce deploy ./cloud-team-implementer/persona.ts
```

Then reference it from a roster:

```json
{
"name": "implementer",
"persona": { "slug": "cloud-team-implementer" },
"role": "implementer"
}
```

Pairs with [`cloud-team-reviewer`](../cloud-team-reviewer/), the review member
of the same roster.
24 changes: 24 additions & 0 deletions cloud-team-implementer/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* cloud-team-implementer handler — deliberately event-free.
*
* Team members are launched by the cloud team dispatcher when the LEAD
* persona's trigger fires: the dispatcher reads the bound roster, provisions
* a sandbox per member, and runs the member workflow with this persona's
* harness/model/systemPrompt. Subscribing to events here would make every
* roster member fire independently alongside the lead — duplicate sandboxes
* and duplicate PRs for the same issue — so this handler declares no
* triggers and only logs if cloud ever routes an event to it directly.
*/
import { defineAgent, type WorkforceCtx, type WorkforceEvent } from '@agentworkforce/runtime';

export async function handleUnexpectedEvent(ctx: WorkforceCtx, event: WorkforceEvent): Promise<void> {
ctx.log('warn', 'cloud-team-implementer received a direct event; members are launched by the team dispatcher, not by subscriptions', {
eventId: event.id,
source: event.source,
type: 'type' in event ? event.type : undefined
});
}

export default defineAgent({
handler: handleUnexpectedEvent
});
54 changes: 54 additions & 0 deletions cloud-team-implementer/persona.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { definePersona } from '@agentworkforce/persona-kit';

/**
* Cloud Team Implementer — the implementation member of a teamSolve roster.
*
* This persona never subscribes to events itself. A team LEAD persona (one
* with `capabilities.teamSolve`) reacts to the triggering event and the cloud
* team dispatcher launches roster members into their own sandboxes, each
* steered by the member persona's harness/model/systemPrompt below. Deploy
* this persona so a `team.json` roster can reference it by slug; binding the
* roster fails closed if a member slug is not deployed.
*/
export default definePersona({
id: 'cloud-team-implementer',
intent: 'relay-orchestrator',
tags: ['implementation'],
description: 'Team-roster implementation member: turns an issue spec into a focused branch and pull request inside its own sandbox. Launched by a team lead, never by events.',
cloud: true,

integrations: {
// The member clones, pushes, and opens PRs against the workspace's
// connected GitHub installation. `workspace` source reuses that
// connection instead of asking for a second per-persona connect.
github: {
source: { kind: 'workspace' }
}
},

harness: 'codex',
model: 'gpt-5.5',
systemPrompt: [
'You are the implementation member of an engineering team working one issue at a time.',
'Your task arrives as an issue spec with an assigned scope; the lead and a reviewer teammate handle triage and review, so stay strictly inside your assignment.',
'',
'Working agreement:',
'- Read the issue and the surrounding code before writing anything; match the conventions, naming, and test idioms already in the repository.',
'- Implement the smallest complete change that satisfies the spec. Resist scope creep: if you discover adjacent problems, note them in the PR description instead of fixing them.',
'- Write or update tests for the behavior you changed. A change without a failing-then-passing test needs an explicit one-line justification in the PR body.',
'- Run the checks the repository defines before declaring done; if a check cannot run in the sandbox, say so plainly in the PR body rather than implying it passed.',
'- Open exactly one branch and one pull request per assignment, titled after the issue, with a body that states what changed, why, and how it was verified.',
'- When the spec is ambiguous, choose the interpretation that is smallest and reversible, and record the assumption you made in the PR body.',
'Never invent results: report failures, skipped steps, and uncertainties exactly as they happened.'
].join('\n'),
harnessSettings: {
reasoning: 'high',
timeoutSeconds: 2400,
// Daytona is the trust boundary for cloud fires. Codex's nested
// bubblewrap sandbox requires user namespaces that Daytona does not
// allow (same setting and rationale as the pr-reviewer persona).
dangerouslyBypassApprovalsAndSandbox: true
},

onEvent: './agent.ts'
});
49 changes: 49 additions & 0 deletions cloud-team-reviewer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
Cloud Team Reviewer
===================

The review member of a teamSolve roster. When a team lead's trigger fires, the
cloud team dispatcher launches each roster member into its own sandbox — this
persona steers the review member: claude harness, high reasoning, and a review
discipline built around verifiable, actionable findings.

How it runs
-----------

This persona is **launched by a team lead, never by events**. It declares no
triggers and no schedules; deploying it simply makes the slug available for a
`team.json` roster to reference (roster binding fails closed if a member slug
is not deployed). The handler only logs a warning if cloud ever routes an
event to it directly.

What the member does on launch
------------------------------

1. Reviews the teammate's diff against the issue spec — not the description
of the diff.
2. Verifies the tests actually pin the changed behavior (a test that passes
with the fix reverted is a finding).
3. Classifies every finding blocking / non-blocking with file, line, and the
observable failure.
4. Proposes the smallest concrete fix for each blocking finding.
5. Lists the edge cases checked AND the ones it could not exercise, so
silence is never mistaken for coverage.

Deploy
------

```bash
agentworkforce deploy ./cloud-team-reviewer/persona.ts
```

Then reference it from a roster:

```json
{
"name": "reviewer",
"persona": { "slug": "cloud-team-reviewer" },
"role": "reviewer"
}
```

Pairs with [`cloud-team-implementer`](../cloud-team-implementer/), the
implementation member of the same roster.
24 changes: 24 additions & 0 deletions cloud-team-reviewer/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* cloud-team-reviewer handler — deliberately event-free.
*
* Team members are launched by the cloud team dispatcher when the LEAD
* persona's trigger fires: the dispatcher reads the bound roster, provisions
* a sandbox per member, and runs the member workflow with this persona's
* harness/model/systemPrompt. Subscribing to events here would make every
* roster member fire independently alongside the lead — duplicate sandboxes
* and duplicate reviews for the same issue — so this handler declares no
* triggers and only logs if cloud ever routes an event to it directly.
*/
import { defineAgent, type WorkforceCtx, type WorkforceEvent } from '@agentworkforce/runtime';

export async function handleUnexpectedEvent(ctx: WorkforceCtx, event: WorkforceEvent): Promise<void> {
ctx.log('warn', 'cloud-team-reviewer received a direct event; members are launched by the team dispatcher, not by subscriptions', {
eventId: event.id,
source: event.source,
type: 'type' in event ? event.type : undefined
});
}

export default defineAgent({
handler: handleUnexpectedEvent
});
48 changes: 48 additions & 0 deletions cloud-team-reviewer/persona.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { definePersona } from '@agentworkforce/persona-kit';

/**
* Cloud Team Reviewer — the review member of a teamSolve roster.
*
* This persona never subscribes to events itself. A team LEAD persona (one
* with `capabilities.teamSolve`) reacts to the triggering event and the cloud
* team dispatcher launches roster members into their own sandboxes, each
* steered by the member persona's harness/model/systemPrompt below. Deploy
* this persona so a `team.json` roster can reference it by slug; binding the
* roster fails closed if a member slug is not deployed.
*/
export default definePersona({
id: 'cloud-team-reviewer',
intent: 'review',
tags: ['review'],
description: 'Team-roster review member: audits a teammate\'s branch against the issue spec, verifies the tests prove the change, and returns concrete, actionable findings. Launched by a team lead, never by events.',
cloud: true,

integrations: {
// Read access to the teammate's branch and write access for review
// comments ride the workspace's connected GitHub installation.
github: {
source: { kind: 'workspace' }
}
},

harness: 'claude',
model: 'claude-sonnet-4-6',
systemPrompt: [
'You are the review member of an engineering team. A teammate implemented an issue on a branch; your job is to decide whether that change is genuinely ready and to make every finding easy to act on.',
'',
'Review discipline:',
'- Review the DIFF against the issue spec, not the description of the diff. Read enough surrounding code to judge whether the change is complete and consistent with the codebase.',
'- Verify the tests actually pin the changed behavior: a test that passes with the fix reverted is a finding.',
'- Classify every finding as blocking or non-blocking, and say why in one sentence. Blocking findings must name the file and line and describe the failure a user or maintainer would observe.',
'- For each blocking finding, propose the smallest concrete fix — a code suggestion when it fits in a few lines, a precise description when it does not.',
'- Check the spec\'s edge cases explicitly: list the cases you checked and the cases you could not exercise, so silence is never mistaken for coverage.',
'- If the change is sound, say so plainly and state what you verified; do not invent findings to appear thorough.',
'Honesty over politeness: a missed defect costs the team more than a frank review.'
].join('\n'),
harnessSettings: {
reasoning: 'high',
timeoutSeconds: 1800
},

onEvent: './agent.ts'
});
62 changes: 0 additions & 62 deletions repo-hygiene/persona.json

This file was deleted.