heyio 3.2.3 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/api/routes/squads.js +6 -6
  2. package/dist/api/routes/squads.js.map +1 -1
  3. package/dist/copilot/tools.d.ts.map +1 -1
  4. package/dist/copilot/tools.js +19 -6
  5. package/dist/copilot/tools.js.map +1 -1
  6. package/dist/squad/agent.d.ts +5 -0
  7. package/dist/squad/agent.d.ts.map +1 -1
  8. package/dist/squad/agent.js +10 -1
  9. package/dist/squad/agent.js.map +1 -1
  10. package/dist/squad/execution/index.d.ts +7 -5
  11. package/dist/squad/execution/index.d.ts.map +1 -1
  12. package/dist/squad/execution/index.js +4 -3
  13. package/dist/squad/execution/index.js.map +1 -1
  14. package/dist/squad/execution/instance.js +1 -1
  15. package/dist/squad/execution/instance.js.map +1 -1
  16. package/dist/squad/execution/planning.d.ts +20 -0
  17. package/dist/squad/execution/planning.d.ts.map +1 -0
  18. package/dist/squad/execution/planning.js +62 -0
  19. package/dist/squad/execution/planning.js.map +1 -0
  20. package/dist/squad/execution/review.d.ts +21 -0
  21. package/dist/squad/execution/review.d.ts.map +1 -0
  22. package/dist/squad/execution/review.js +151 -0
  23. package/dist/squad/execution/review.js.map +1 -0
  24. package/dist/squad/execution/runner.d.ts +32 -7
  25. package/dist/squad/execution/runner.d.ts.map +1 -1
  26. package/dist/squad/execution/runner.js +40 -25
  27. package/dist/squad/execution/runner.js.map +1 -1
  28. package/dist/squad/execution/tasks.d.ts +13 -2
  29. package/dist/squad/execution/tasks.d.ts.map +1 -1
  30. package/dist/squad/execution/tasks.js +58 -59
  31. package/dist/squad/execution/tasks.js.map +1 -1
  32. package/node_modules/@io/shared/dist/types/events.d.ts +1 -1
  33. package/node_modules/@io/shared/dist/types/events.d.ts.map +1 -1
  34. package/node_modules/@io/shared/package.json +1 -1
  35. package/node_modules/@io/shared/src/types/events.ts +2 -0
  36. package/node_modules/@io/shared/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +1 -1
  38. package/dist/squad/execution/meeting.d.ts +0 -30
  39. package/dist/squad/execution/meeting.d.ts.map +0 -1
  40. package/dist/squad/execution/meeting.js +0 -147
  41. package/dist/squad/execution/meeting.js.map +0 -1
@@ -0,0 +1,62 @@
1
+ import { createChildLogger } from '../../logging/logger.js';
2
+ import { getEventBus } from '../event-bus.js';
3
+ import { parseTierHint } from '../model-selector.js';
4
+ import { transitionInstance } from './instance.js';
5
+ const logger = () => createChildLogger('planning');
6
+ /**
7
+ * Team Lead plans the instance alone — one LLM call to produce a task list.
8
+ * No round-table, no consensus, no veto at planning stage.
9
+ */
10
+ export async function planInstance(params) {
11
+ const log = logger();
12
+ const { instance, runtime, objective, attachments } = params;
13
+ // Transition to planning (already in 'planning' from createInstance, transition to working skipped — we use a direct status)
14
+ const teamLead = runtime.members.get('technical-pm');
15
+ if (!teamLead)
16
+ throw new Error('No team lead available for planning');
17
+ // Track activity under this instance
18
+ teamLead.setInstanceId(instance.id);
19
+ // Build roster description so the lead knows who's available
20
+ const roster = [...runtime.members.entries()]
21
+ .filter(([role]) => role !== 'technical-pm')
22
+ .map(([role]) => `- ${role}`)
23
+ .join('\n');
24
+ const attachmentNote = attachments?.length
25
+ ? `\n\nThe user has provided ${attachments.length} file(s) as reference material. They are attached to this message — review them as part of your planning.`
26
+ : '';
27
+ const taskPlan = await teamLead.send(`You are the team lead. Plan the following objective and produce a task list for your team.\n\nObjective: ${objective}${attachmentNote}\n\nYour team members (by role):\n${roster}\n\nFor each task, specify:\n1. A brief description of the work\n2. Which team member role should do it (must match a role above)\n3. The model tier needed (fast for simple edits/docs, standard for typical coding, reasoning for complex architecture/analysis)\n\nFormat each task as: "TASK: <description> | ASSIGN: <role> | MODEL_TIER: <fast|standard|reasoning>"\n\nChoose the lowest tier that can handle each task to minimize cost. Tasks will execute in parallel, so ensure they are independent and don't conflict on the same files.`, attachments);
28
+ const tasks = parseTaskList(taskPlan, instance.id);
29
+ instance.tasks = tasks;
30
+ instance.meetingLog = [`[technical-pm] Plan:\n${taskPlan}`];
31
+ await getEventBus().emit({
32
+ id: crypto.randomUUID(),
33
+ timestamp: new Date(),
34
+ type: 'instance:planning_complete',
35
+ squadId: instance.squadId,
36
+ instanceId: instance.id,
37
+ data: { taskCount: tasks.length, objective },
38
+ });
39
+ log.info({ instanceId: instance.id, tasks: tasks.length }, 'Planning complete');
40
+ return { tasks };
41
+ }
42
+ /** Parse the team lead's task list into structured tasks */
43
+ function parseTaskList(taskPlan, instanceId) {
44
+ const tasks = [];
45
+ const lines = taskPlan.split('\n');
46
+ for (const line of lines) {
47
+ const match = line.match(/TASK:\s*(.+?)\s*\|\s*ASSIGN:\s*([^|]+)(?:\s*\|\s*MODEL_TIER:\s*(\w+))?/i);
48
+ if (match) {
49
+ const tierHint = parseTierHint(match[3]);
50
+ tasks.push({
51
+ id: crypto.randomUUID(),
52
+ description: match[1].trim(),
53
+ assignedTo: match[2].trim().toLowerCase().replace(/\s+/g, '-'),
54
+ status: 'pending',
55
+ modelTier: tierHint,
56
+ retryCount: 0,
57
+ });
58
+ }
59
+ }
60
+ return tasks;
61
+ }
62
+ //# sourceMappingURL=planning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planning.js","sourceRoot":"","sources":["../../../src/squad/execution/planning.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { SquadRuntime } from '../manager.js';
2
+ import type { Instance } from './instance.js';
3
+ export interface ReviewResult {
4
+ approved: boolean;
5
+ cycles: number;
6
+ failureReason?: string;
7
+ }
8
+ /**
9
+ * Gated review cycle:
10
+ * 1. Lead reviews all task results
11
+ * 2. If lead rejects → identifies tasks to rework, specialists rework in parallel
12
+ * 3. If lead approves → QA/veto reviews
13
+ * 4. If QA rejects → same rework loop
14
+ * 5. Max 5 cycles total, then fail to inbox
15
+ */
16
+ export declare function reviewWork(params: {
17
+ instance: Instance;
18
+ runtime: SquadRuntime;
19
+ objective: string;
20
+ }): Promise<ReviewResult>;
21
+ //# sourceMappingURL=review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../../src/squad/execution/review.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,eAAe,CAAC;AAQ5D,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,YAAY,CAAC,CAyHxB"}
@@ -0,0 +1,151 @@
1
+ import { createChildLogger } from '../../logging/logger.js';
2
+ import { getEventBus } from '../event-bus.js';
3
+ import { selectModelForRole } from '../model-selector.js';
4
+ import { addInboxEntry } from '../../store/inbox.js';
5
+ import { transitionInstance } from './instance.js';
6
+ import { executeRework } from './tasks.js';
7
+ const logger = () => createChildLogger('review');
8
+ const MAX_REVIEW_CYCLES = 5;
9
+ /**
10
+ * Gated review cycle:
11
+ * 1. Lead reviews all task results
12
+ * 2. If lead rejects → identifies tasks to rework, specialists rework in parallel
13
+ * 3. If lead approves → QA/veto reviews
14
+ * 4. If QA rejects → same rework loop
15
+ * 5. Max 5 cycles total, then fail to inbox
16
+ */
17
+ export async function reviewWork(params) {
18
+ const log = logger();
19
+ const { instance, runtime, objective } = params;
20
+ await transitionInstance(instance.id, 'reviewing');
21
+ const teamLead = runtime.members.get('technical-pm');
22
+ if (!teamLead)
23
+ throw new Error('No team lead for review');
24
+ // Track review activity under this instance
25
+ teamLead.setInstanceId(instance.id);
26
+ // Find veto/QA members
27
+ const vetoMembers = [...runtime.members.entries()].filter(([role]) => {
28
+ const skill = runtime.skills.get(role);
29
+ return skill?.veto && role !== 'technical-pm';
30
+ });
31
+ let cycles = 0;
32
+ while (cycles < MAX_REVIEW_CYCLES) {
33
+ cycles++;
34
+ log.info({ instanceId: instance.id, cycle: cycles }, 'Review cycle');
35
+ await getEventBus().emit({
36
+ id: crypto.randomUUID(),
37
+ timestamp: new Date(),
38
+ type: 'instance:review_cycle',
39
+ squadId: instance.squadId,
40
+ instanceId: instance.id,
41
+ data: { cycle: cycles, maxCycles: MAX_REVIEW_CYCLES },
42
+ });
43
+ // Build task summary for reviewer
44
+ const taskSummary = instance.tasks
45
+ .map((t) => `- [${t.status}] ${t.description} (${t.assignedTo})\n Result: ${(t.result ?? 'No result').slice(0, 1000)}`)
46
+ .join('\n\n');
47
+ // Step 1: Team Lead reviews
48
+ const reviewModel = selectModelForRole('technical-pm', 'review');
49
+ if (teamLead.getModel() !== reviewModel) {
50
+ await teamLead.switchModel(reviewModel);
51
+ }
52
+ const leadReview = await teamLead.send(`Review all completed work for this objective:\n\nObjective: ${objective}\n\nTask results:\n${taskSummary}\n\nDoes the work meet the objective? Reply with one of:\n- "APPROVED" if all work is satisfactory\n- "REWORK:" followed by a JSON array of objects with "taskId" and "feedback" for each task that needs revision. Example:\nREWORK: [{"taskId": "abc-123", "feedback": "Missing error handling"}]`);
53
+ if (leadReview.toUpperCase().includes('APPROVED')) {
54
+ // Step 2: QA/veto review (gated behind lead approval)
55
+ if (vetoMembers.length === 0) {
56
+ log.info({ instanceId: instance.id }, 'No veto members, lead approval is final');
57
+ return { approved: true, cycles };
58
+ }
59
+ for (const [role, agent] of vetoMembers) {
60
+ agent.setInstanceId(instance.id);
61
+ const qaModel = selectModelForRole(role, 'review');
62
+ if (agent.getModel() !== qaModel) {
63
+ await agent.switchModel(qaModel);
64
+ }
65
+ const qaReview = await agent.send(`As QA, review the following completed work:\n\nObjective: ${objective}\n\nTask results:\n${taskSummary}\n\nDoes this meet quality standards? Reply with:\n- "APPROVED" if satisfactory\n- "REWORK:" followed by a JSON array of objects with "taskId" and "feedback" for tasks that need revision.`);
66
+ if (qaReview.toUpperCase().includes('REWORK:')) {
67
+ // QA rejected — parse rework instructions and loop
68
+ const reworkTasks = parseReworkInstructions(qaReview, instance.tasks);
69
+ if (reworkTasks.length > 0) {
70
+ log.info({ instanceId: instance.id, cycle: cycles, rejectedBy: role, reworkCount: reworkTasks.length }, 'QA rejected, reworking');
71
+ await transitionInstance(instance.id, 'working');
72
+ await executeRework({ instance, runtime, reworkTasks });
73
+ await transitionInstance(instance.id, 'reviewing');
74
+ }
75
+ break; // Back to top of review loop
76
+ }
77
+ }
78
+ // If we didn't break (all QA approved), we're done
79
+ if (!leadReview.toUpperCase().includes('REWORK:')) {
80
+ // Check that we actually reached this point without a QA rejection
81
+ const allQaApproved = true; // If we didn't break, all approved
82
+ if (allQaApproved) {
83
+ log.info({ instanceId: instance.id, cycles }, 'All reviewers approved');
84
+ return { approved: true, cycles };
85
+ }
86
+ }
87
+ }
88
+ else if (leadReview.toUpperCase().includes('REWORK:')) {
89
+ // Lead rejected — parse rework and loop
90
+ const reworkTasks = parseReworkInstructions(leadReview, instance.tasks);
91
+ if (reworkTasks.length > 0) {
92
+ log.info({ instanceId: instance.id, cycle: cycles, reworkCount: reworkTasks.length }, 'Lead rejected, reworking');
93
+ await transitionInstance(instance.id, 'working');
94
+ await executeRework({ instance, runtime, reworkTasks });
95
+ await transitionInstance(instance.id, 'reviewing');
96
+ }
97
+ else {
98
+ // Couldn't parse rework instructions — treat as approved to avoid infinite loop
99
+ log.warn({ instanceId: instance.id }, 'Could not parse rework instructions, treating as approved');
100
+ return { approved: true, cycles };
101
+ }
102
+ }
103
+ else {
104
+ // Ambiguous response — treat as approved
105
+ log.warn({ instanceId: instance.id }, 'Ambiguous review response, treating as approved');
106
+ return { approved: true, cycles };
107
+ }
108
+ }
109
+ // Exhausted review cycles — send to inbox
110
+ const failureReason = `Failed to pass review after ${MAX_REVIEW_CYCLES} cycles for objective: ${objective}`;
111
+ log.error({ instanceId: instance.id }, failureReason);
112
+ await addInboxEntry({
113
+ squadId: instance.squadId,
114
+ instanceId: instance.id,
115
+ kind: 'note',
116
+ title: `Review failed: ${objective.slice(0, 60)}`,
117
+ content: `Instance ${instance.id} exhausted ${MAX_REVIEW_CYCLES} review/rework cycles without reaching approval.\n\nObjective: ${objective}\n\nFinal task states:\n${instance.tasks.map((t) => `- [${t.status}] ${t.description}: ${(t.result ?? 'no result').slice(0, 200)}`).join('\n')}`,
118
+ });
119
+ return { approved: false, cycles, failureReason };
120
+ }
121
+ /**
122
+ * Parse rework instructions from a review response.
123
+ * Expects JSON array after "REWORK:" with {taskId, feedback} objects.
124
+ * Falls back to assigning feedback to all non-done tasks if parsing fails.
125
+ */
126
+ function parseReworkInstructions(response, tasks) {
127
+ const reworkMatch = response.match(/REWORK:\s*(\[[\s\S]*?\])/i);
128
+ if (reworkMatch) {
129
+ try {
130
+ const parsed = JSON.parse(reworkMatch[1]);
131
+ if (Array.isArray(parsed)) {
132
+ return parsed
133
+ .filter((item) => item.taskId && item.feedback)
134
+ .map((item) => ({
135
+ taskId: item.taskId,
136
+ feedback: item.feedback,
137
+ }));
138
+ }
139
+ }
140
+ catch {
141
+ // Fall through to fallback
142
+ }
143
+ }
144
+ // Fallback: extract plain-text feedback and apply to all completed tasks
145
+ const feedbackMatch = response.match(/REWORK:\s*([\s\S]+)/i);
146
+ const feedback = feedbackMatch?.[1]?.trim() ?? 'Please review and fix issues.';
147
+ return tasks
148
+ .filter((t) => t.status === 'done' || t.status === 'failed')
149
+ .map((t) => ({ taskId: t.id, feedback }));
150
+ }
151
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../../src/squad/execution/review.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,43 @@
1
1
  import type { Squad } from '@io/shared';
2
- import { type PrResult } from './index.js';
2
+ import { type SquadRuntime } from '../manager.js';
3
+ import { type Instance, type PrResult } from './index.js';
3
4
  export interface RunResult {
4
5
  instanceId: string;
5
6
  success: boolean;
6
7
  pr?: PrResult | null;
7
8
  error?: string;
8
9
  }
10
+ export interface InitResult {
11
+ instance: Instance;
12
+ runtime: SquadRuntime;
13
+ }
14
+ /**
15
+ * Initialize an instance: boot the squad runtime and persist the instance to DB.
16
+ * This is the critical part that MUST succeed before we tell the user "started."
17
+ */
18
+ export declare function initInstance(params: {
19
+ squad: Squad;
20
+ objective: string;
21
+ issueRef?: string;
22
+ }): Promise<InitResult>;
23
+ /**
24
+ * Execute an already-initialized instance through its full lifecycle:
25
+ * planning → tasks → review → PR → cleanup
26
+ */
27
+ export declare function executeInstance(params: {
28
+ instance: Instance;
29
+ runtime: SquadRuntime;
30
+ squad: Squad;
31
+ objective: string;
32
+ attachments?: Array<{
33
+ type: 'file';
34
+ path: string;
35
+ displayName?: string;
36
+ }>;
37
+ }): Promise<RunResult>;
9
38
  /**
10
- * Run a full instance lifecycle:
11
- * 1. Create instance (with worktree)
12
- * 2. Hold round-table meeting
13
- * 3. Execute tasks
14
- * 4. Create PR
15
- * 5. Clean up
39
+ * Run a full instance lifecycle (init + execute).
40
+ * Convenience wrapper for callers that don't need to split the phases.
16
41
  */
17
42
  export declare function runInstance(params: {
18
43
  squad: Squad;
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/squad/execution/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,EAEN,KAAK,QAAQ,EAMb,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,SAAS;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE;IACzC,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E,GAAG,OAAO,CAAC,SAAS,CAAC,CA+DrB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/squad/execution/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAAE,KAAK,YAAY,EAA8B,MAAM,eAAe,CAAC;AAC9E,OAAO,EACN,KAAK,QAAQ,EACb,KAAK,QAAQ,EAOb,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,SAAS;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE;IAC1C,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,UAAU,CAAC,CAatB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E,GAAG,OAAO,CAAC,SAAS,CAAC,CA0DrB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE;IACzC,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E,GAAG,OAAO,CAAC,SAAS,CAAC,CAMrB"}
@@ -1,51 +1,57 @@
1
1
  import { createChildLogger } from '../../logging/logger.js';
2
2
  import { bootSquad, getSquadRuntime } from '../manager.js';
3
- import { cleanupInstance, createInstance, createPullRequest, executeTasks, runMeeting, } from './index.js';
3
+ import { cleanupInstance, createInstance, createPullRequest, executeTasks, planInstance, reviewWork, } from './index.js';
4
4
  const logger = () => createChildLogger('runner');
5
5
  /**
6
- * Run a full instance lifecycle:
7
- * 1. Create instance (with worktree)
8
- * 2. Hold round-table meeting
9
- * 3. Execute tasks
10
- * 4. Create PR
11
- * 5. Clean up
6
+ * Initialize an instance: boot the squad runtime and persist the instance to DB.
7
+ * This is the critical part that MUST succeed before we tell the user "started."
12
8
  */
13
- export async function runInstance(params) {
14
- const log = logger();
15
- const { squad, objective, issueRef, attachments } = params;
9
+ export async function initInstance(params) {
10
+ const { squad, objective, issueRef } = params;
16
11
  // Ensure squad is booted
17
12
  let runtime = getSquadRuntime(squad.id);
18
13
  if (!runtime) {
19
14
  runtime = await bootSquad(squad);
20
15
  }
21
- // 1. Create instance
16
+ // Create instance (persists to DB + creates worktree)
22
17
  const instance = await createInstance({ squad, issueRef, objective });
23
- log.info({ instanceId: instance.id }, 'Starting instance run');
18
+ return { instance, runtime };
19
+ }
20
+ /**
21
+ * Execute an already-initialized instance through its full lifecycle:
22
+ * planning → tasks → review → PR → cleanup
23
+ */
24
+ export async function executeInstance(params) {
25
+ const log = logger();
26
+ const { instance, runtime, squad, objective, attachments } = params;
27
+ log.info({ instanceId: instance.id }, 'Starting instance execution');
24
28
  try {
25
- // 2. Run meeting
26
- const meetingResult = await runMeeting({ instance, runtime, objective, attachments });
27
- if (!meetingResult.consensus) {
28
- log.warn({ instanceId: instance.id }, 'Meeting did not reach consensus');
29
+ // Team Lead plans
30
+ await planInstance({ instance, runtime, objective, attachments });
31
+ if (instance.tasks.length === 0) {
32
+ log.warn({ instanceId: instance.id }, 'No tasks generated from planning');
29
33
  return {
30
34
  instanceId: instance.id,
31
35
  success: false,
32
- error: `Meeting failed to reach consensus${meetingResult.vetoReason ? `: ${meetingResult.vetoReason}` : ''}`,
36
+ error: 'Planning produced no actionable tasks',
33
37
  };
34
38
  }
35
- if (instance.tasks.length === 0) {
36
- log.warn({ instanceId: instance.id }, 'No tasks generated from meeting');
39
+ // Execute tasks in parallel
40
+ await executeTasks({ instance, runtime });
41
+ // Gated review/rework cycles
42
+ const reviewResult = await reviewWork({ instance, runtime, objective });
43
+ if (!reviewResult.approved) {
44
+ await cleanupInstance(instance.id, squad);
37
45
  return {
38
46
  instanceId: instance.id,
39
47
  success: false,
40
- error: 'Meeting produced no actionable tasks',
48
+ error: reviewResult.failureReason ?? 'Review failed',
41
49
  };
42
50
  }
43
- // 3. Execute tasks
44
- await executeTasks({ instance, runtime });
45
- // 4. Create PR
51
+ // Create PR
46
52
  const prTitle = objective.slice(0, 72);
47
53
  const pr = await createPullRequest({ instance, title: prTitle, squadName: squad.name });
48
- // 5. Cleanup (if no PR was created — otherwise keep the branch for review)
54
+ // Cleanup (if no PR was created — otherwise keep the branch for review)
49
55
  if (!pr) {
50
56
  await cleanupInstance(instance.id, squad);
51
57
  }
@@ -57,7 +63,7 @@ export async function runInstance(params) {
57
63
  }
58
64
  catch (err) {
59
65
  const errMsg = err instanceof Error ? err.message : String(err);
60
- log.error({ instanceId: instance.id, error: errMsg.slice(0, 300) }, 'Instance run failed');
66
+ log.error({ instanceId: instance.id, error: errMsg.slice(0, 300) }, 'Instance execution failed');
61
67
  await cleanupInstance(instance.id, squad);
62
68
  return {
63
69
  instanceId: instance.id,
@@ -66,4 +72,13 @@ export async function runInstance(params) {
66
72
  };
67
73
  }
68
74
  }
75
+ /**
76
+ * Run a full instance lifecycle (init + execute).
77
+ * Convenience wrapper for callers that don't need to split the phases.
78
+ */
79
+ export async function runInstance(params) {
80
+ const { squad, objective, issueRef, attachments } = params;
81
+ const { instance, runtime } = await initInstance({ squad, objective, issueRef });
82
+ return executeInstance({ instance, runtime, squad, objective, attachments });
83
+ }
69
84
  //# sourceMappingURL=runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/squad/execution/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/squad/execution/runner.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,22 @@
1
1
  import type { SquadRuntime } from '../manager.js';
2
2
  import { type Instance } from './instance.js';
3
3
  /**
4
- * Execute all tasks in an instance sequentially.
5
- * Team lead reviews each completed task before moving to the next.
4
+ * Execute all tasks in parallel.
5
+ * No per-task review that's handled by the review phase.
6
6
  */
7
7
  export declare function executeTasks(params: {
8
8
  instance: Instance;
9
9
  runtime: SquadRuntime;
10
10
  }): Promise<void>;
11
+ /**
12
+ * Execute tasks that need rework (called during review cycles).
13
+ */
14
+ export declare function executeRework(params: {
15
+ instance: Instance;
16
+ runtime: SquadRuntime;
17
+ reworkTasks: Array<{
18
+ taskId: string;
19
+ feedback: string;
20
+ }>;
21
+ }): Promise<void>;
11
22
  //# sourceMappingURL=tasks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../../src/squad/execution/tasks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,KAAK,QAAQ,EAAyC,MAAM,eAAe,CAAC;AAIrF;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmGhB"}
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../../src/squad/execution/tasks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,KAAK,QAAQ,EAAyC,MAAM,eAAe,CAAC;AAIrF;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAehB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC3C,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzD,GAAG,OAAO,CAAC,IAAI,CAAC,CA0ChB"}
@@ -1,11 +1,10 @@
1
1
  import { createChildLogger } from '../../logging/logger.js';
2
- import { getEventBus } from '../event-bus.js';
3
- import { selectModelForRole, selectModelForTask } from '../model-selector.js';
2
+ import { selectModelForTask } from '../model-selector.js';
4
3
  import { transitionInstance } from './instance.js';
5
4
  const logger = () => createChildLogger('task-exec');
6
5
  /**
7
- * Execute all tasks in an instance sequentially.
8
- * Team lead reviews each completed task before moving to the next.
6
+ * Execute all tasks in parallel.
7
+ * No per-task review that's handled by the review phase.
9
8
  */
10
9
  export async function executeTasks(params) {
11
10
  const log = logger();
@@ -14,77 +13,77 @@ export async function executeTasks(params) {
14
13
  const teamLead = runtime.members.get('technical-pm');
15
14
  if (!teamLead)
16
15
  throw new Error('No team lead for task execution');
17
- for (const task of instance.tasks) {
18
- if (task.status === 'done')
19
- continue;
20
- log.info({ taskId: task.id, assignedTo: task.assignedTo, modelTier: task.modelTier }, 'Executing task');
16
+ // Execute all tasks concurrently
17
+ await Promise.all(instance.tasks
18
+ .filter((task) => task.status !== 'done')
19
+ .map((task) => executeTask(task, instance, runtime, log)));
20
+ }
21
+ /**
22
+ * Execute tasks that need rework (called during review cycles).
23
+ */
24
+ export async function executeRework(params) {
25
+ const log = logger();
26
+ const { instance, runtime, reworkTasks } = params;
27
+ await Promise.all(reworkTasks.map(async ({ taskId, feedback }) => {
28
+ const task = instance.tasks.find((t) => t.id === taskId);
29
+ if (!task)
30
+ return;
31
+ task.retryCount++;
21
32
  task.status = 'in_progress';
22
33
  const agent = runtime.members.get(task.assignedTo);
23
34
  if (!agent) {
24
- log.warn({ role: task.assignedTo }, 'No agent for assigned role, team lead will handle');
25
- // Reassign to team lead for delegation decision
26
- task.result = `No agent with role '${task.assignedTo}' available.`;
27
35
  task.status = 'failed';
28
- continue;
36
+ task.result = `No agent with role '${task.assignedTo}' available.`;
37
+ return;
29
38
  }
30
- // Select model based on task tier and retry count
31
- const taskModel = selectModelForTask(task.modelTier, task.retryCount);
32
- if (agent.getModel() !== taskModel) {
33
- await agent.switchModel(taskModel);
39
+ // Track activity under this instance
40
+ agent.setInstanceId(instance.id);
41
+ const model = selectModelForTask(task.modelTier, task.retryCount);
42
+ if (agent.getModel() !== model) {
43
+ await agent.switchModel(model);
34
44
  }
35
45
  try {
36
- // Agent executes the task
37
46
  const workingDir = instance.worktree?.path ?? '';
38
- const taskPrompt = buildTaskPrompt(task, workingDir, instance);
39
- const result = await agent.send(taskPrompt);
47
+ const result = await agent.send(`Your previous work on "${task.description}" needs revision.\n\nFeedback: ${feedback}\n\n${workingDir ? `Working directory: ${workingDir}\n\n` : ''}Please address this feedback and report your updated results.`);
40
48
  task.result = result;
41
- // Team lead reviews (switch to reasoning for review)
42
- const reviewModel = selectModelForRole('technical-pm', 'review');
43
- if (teamLead.getModel() !== reviewModel) {
44
- await teamLead.switchModel(reviewModel);
45
- }
46
- const review = await teamLead.send(`An agent (${task.assignedTo}) completed a task. Review their work:\n\nTask: ${task.description}\n\nAgent's report:\n${result.slice(0, 2000)}\n\nIs this satisfactory? Reply with:\n- "APPROVED" if the work meets requirements\n- "REDO: <feedback>" if it needs changes`);
47
- if (review.toUpperCase().includes('APPROVED')) {
48
- task.status = 'done';
49
- log.info({ taskId: task.id }, 'Task approved');
50
- }
51
- else if (review.toUpperCase().includes('REDO:')) {
52
- // Retry with escalated model
53
- task.retryCount++;
54
- const escalatedModel = selectModelForTask(task.modelTier, task.retryCount);
55
- log.info({ taskId: task.id, retryCount: task.retryCount, model: escalatedModel }, 'Task needs revision, escalating model');
56
- if (agent.getModel() !== escalatedModel) {
57
- await agent.switchModel(escalatedModel);
58
- }
59
- const feedback = review.replace(/^.*REDO:\s*/i, '');
60
- const retry = await agent.send(`Your work on "${task.description}" needs revision. Feedback from team lead:\n\n${feedback}\n\nPlease address this feedback and report your updated results.`);
61
- task.result = retry;
62
- task.status = 'done'; // Accept after one retry
63
- log.info({ taskId: task.id }, 'Task completed after revision with escalated model');
64
- }
65
- else {
66
- task.status = 'done';
67
- }
49
+ task.status = 'done';
50
+ log.info({ taskId: task.id, retryCount: task.retryCount }, 'Rework task completed');
68
51
  }
69
52
  catch (err) {
70
- log.error({ err, taskId: task.id }, 'Task execution failed');
53
+ log.error({ err, taskId: task.id }, 'Rework task failed');
71
54
  task.status = 'failed';
72
55
  task.result = `Error: ${err instanceof Error ? err.message : String(err)}`;
73
56
  }
57
+ }));
58
+ }
59
+ async function executeTask(task, instance, runtime, log) {
60
+ log.info({ taskId: task.id, assignedTo: task.assignedTo, modelTier: task.modelTier }, 'Executing task');
61
+ task.status = 'in_progress';
62
+ const agent = runtime.members.get(task.assignedTo);
63
+ if (!agent) {
64
+ log.warn({ role: task.assignedTo }, 'No agent for assigned role');
65
+ task.result = `No agent with role '${task.assignedTo}' available.`;
66
+ task.status = 'failed';
67
+ return;
68
+ }
69
+ // Track activity under this instance
70
+ agent.setInstanceId(instance.id);
71
+ const model = selectModelForTask(task.modelTier, task.retryCount);
72
+ if (agent.getModel() !== model) {
73
+ await agent.switchModel(model);
74
74
  }
75
- // Move to reviewing phase
76
- await transitionInstance(instance.id, 'reviewing');
77
- // Team lead does final review
78
- const taskSummary = instance.tasks
79
- .map((t) => `- [${t.status}] ${t.description} (${t.assignedTo})`)
80
- .join('\n');
81
- const finalReview = await teamLead.send(`All tasks have been executed. Here's the summary:\n\n${taskSummary}\n\nProvide a final assessment. Should we proceed to create a PR, or are there critical issues? Reply with:\n- "READY_FOR_PR: <PR title>" if ready\n- "NEEDS_WORK: <what's missing>" if not ready`);
82
- if (finalReview.toUpperCase().includes('READY_FOR_PR:')) {
83
- instance.meetingLog.push(`[technical-pm] Final review: ${finalReview}`);
75
+ try {
76
+ const workingDir = instance.worktree?.path ?? '';
77
+ const taskPrompt = buildTaskPrompt(task, workingDir, instance);
78
+ const result = await agent.send(taskPrompt);
79
+ task.result = result;
80
+ task.status = 'done';
81
+ log.info({ taskId: task.id }, 'Task completed');
84
82
  }
85
- else {
86
- // Mark complete anyway we don't loop indefinitely
87
- instance.meetingLog.push(`[technical-pm] Final review (issues noted): ${finalReview}`);
83
+ catch (err) {
84
+ log.error({ err, taskId: task.id }, 'Task execution failed');
85
+ task.status = 'failed';
86
+ task.result = `Error: ${err instanceof Error ? err.message : String(err)}`;
88
87
  }
89
88
  }
90
89
  function buildTaskPrompt(task, workingDir, instance) {