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
1 change: 1 addition & 0 deletions cloud-team-implementer/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export async function handleUnexpectedEvent(ctx: WorkforceCtx, event: WorkforceE
}

export default defineAgent({
launchedBy: 'team-dispatcher',
handler: handleUnexpectedEvent
});
1 change: 1 addition & 0 deletions cloud-team-reviewer/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export async function handleUnexpectedEvent(ctx: WorkforceCtx, event: WorkforceE
}

export default defineAgent({
launchedBy: 'team-dispatcher',
handler: handleUnexpectedEvent
});
392 changes: 193 additions & 199 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
"compile": "for d in */persona.ts; do agentworkforce persona compile \"$d\"; done"
},
"dependencies": {
"@agentworkforce/persona-kit": "^3.0.41",
"@agentworkforce/runtime": "^3.0.41",
"@agentworkforce/persona-kit": "^3.0.47",
"@agentworkforce/runtime": "^3.0.47",
"@relayfile/relay-helpers": "0.3.33"
},
"devDependencies": {
"@types/node": "^22",
"agentworkforce": "^3.0.41",
"agentworkforce": "^3.0.47",
"esbuild": "^0.25.12",
"typescript": "^5.6.0"
},
Expand Down
6 changes: 3 additions & 3 deletions teams/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ curl -sS -X POST "$CLOUD_API_BASE/api/v1/workspaces/$WORKSPACE_ID/teams" \

Multi-member roster for the deployed `cloud-team-issue` teamSolve agent
(lead-outside-member-list shape: the lead is the deployed agent, the members
are the launchable workers). Both members reference the `cloud-team-issue`
persona slug — the only deployed teamSolve persona and are distinguished by
`name`/`role`.
are the launchable workers). Members reference the deployed
`cloud-team-implementer` and `cloud-team-reviewer` persona slugs and are
distinguished by `name`/`role`.

Binding this roster is one of **three** levers for team N>1 go-live; the other
two live in cloud and the roster stays dormant until they flip:
Expand Down
4 changes: 2 additions & 2 deletions teams/cloud-team-issue/team.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
{
"name": "implementer",
"persona": {
"slug": "cloud-team-issue"
"slug": "cloud-team-implementer"
},
"role": "implementer"
},
{
"name": "reviewer",
"persona": {
"slug": "cloud-team-issue"
"slug": "cloud-team-reviewer"
},
"role": "reviewer"
}
Expand Down
29 changes: 27 additions & 2 deletions tests/team-spec.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,40 @@ for (const teamDir of teamDirs) {
});
}

test('cloud-team-issue roster references the deployed teamSolve persona', () => {
test('cloud-team-issue roster references the deployed member personas', () => {
const specPath = join(teamsRoot, 'cloud-team-issue', 'team.json');
const spec = JSON.parse(readFileSync(specPath, 'utf8'));
assert.deepEqual(
spec.members.map((member) => member.persona?.slug ?? member.persona),
['cloud-team-issue', 'cloud-team-issue'],
['cloud-team-implementer', 'cloud-team-reviewer'],
);
});

test('cloud-team-issue member persona slugs match deployable persona ids', async () => {
const specPath = join(teamsRoot, 'cloud-team-issue', 'team.json');
const spec = JSON.parse(readFileSync(specPath, 'utf8'));
const slugs = spec.members.map((member) => member.persona?.slug ?? member.persona);

for (const slug of slugs) {
const { default: persona } = await import(`../.test-build/${slug}/persona.js`);
assert.equal(persona.id, slug, `${slug} roster ref must match its persona id`);
}
});

test('cloud-team-issue member agents are launched by the dispatcher', async () => {
const specPath = join(teamsRoot, 'cloud-team-issue', 'team.json');
const spec = JSON.parse(readFileSync(specPath, 'utf8'));
const slugs = spec.members.map((member) => member.persona?.slug ?? member.persona);

for (const slug of slugs) {
const { default: agent } = await import(`../.test-build/${slug}/agent.js`);
assert.equal(agent.launchedBy, 'team-dispatcher', `${slug} agent must be dispatcher-launched`);
assert.equal(agent.triggers, undefined, `${slug} agent must not declare direct triggers`);
assert.equal(agent.schedules, undefined, `${slug} agent must not declare direct schedules`);
assert.equal(agent.watch, undefined, `${slug} agent must not declare direct watches`);
}
});

// Validator self-checks: prove each contract rule actually rejects, so a
// future edit that loosens the validator cannot silently green the suite.
const validSpec = {
Expand Down