chatroom-cli 1.131.2 → 1.132.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 (3) hide show
  1. package/dist/index.js +1245 -719
  2. package/dist/index.js.map +101 -53
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20412,6 +20412,10 @@ var init_agent_role = __esm(() => {
20412
20412
  { teamId: "duo", order: 45 },
20413
20413
  { teamId: "solo", order: 45 }
20414
20414
  ]
20415
+ },
20416
+ reviewer: {
20417
+ tags: ["ephemeral" /* Ephemeral */],
20418
+ teams: [{ teamId: "duo", order: 35 }]
20415
20419
  }
20416
20420
  };
20417
20421
  AGENT_ROLE_DEFINITIONS = Object.fromEntries(Object.entries(roleMetadata).map(([role, metadata]) => [role, { role, ...metadata }]));
@@ -100027,7 +100031,7 @@ var init_team_presets = __esm(() => {
100027
100031
  duo: {
100028
100032
  structureId: TEAM_STRUCTURE_IDS.duo,
100029
100033
  name: "Duo",
100030
- description: "A planner and builder working as a pair, planner as coordinator, with optional ephemeral architect, researcher, triage, uiux-engineer, and verifier roles",
100034
+ description: "A planner and builder working as a pair, planner as coordinator, with optional ephemeral architect, researcher, triage, reviewer, uiux-engineer, and verifier roles",
100031
100035
  roles: getBuiltinRolesForTeam("duo"),
100032
100036
  entryPoint: "planner"
100033
100037
  },
@@ -100231,6 +100235,119 @@ var init_agent2 = __esm(() => {
100231
100235
  init_storage2();
100232
100236
  });
100233
100237
 
100238
+ // ../../services/backend/prompts/cli/handoff-templates/pair.ts
100239
+ function normalizeHandoffRole(value2) {
100240
+ if (value2 === undefined)
100241
+ return;
100242
+ const normalized = value2.trim().toLowerCase();
100243
+ return normalized === "" ? undefined : normalized;
100244
+ }
100245
+ function normalizeHandoffMode(value2) {
100246
+ if (value2 === undefined)
100247
+ return;
100248
+ const normalized = value2.trim().toLowerCase();
100249
+ return normalized === "" ? undefined : normalized;
100250
+ }
100251
+ function isConversationMode2(value2) {
100252
+ return CONVERSATION_MODES.includes(value2);
100253
+ }
100254
+ function modeBucket(mode) {
100255
+ return mode === "chat" ? "chat" : "code";
100256
+ }
100257
+ function formatHandoffTemplateKey(selection) {
100258
+ const { pair, mode } = selection;
100259
+ return `${pair.teamId}:${pair.fromRole}->${pair.toRole}@${modeBucket(mode)}`;
100260
+ }
100261
+ function isTeamPresetId(value2) {
100262
+ return TEAM_PRESET_IDS.includes(value2);
100263
+ }
100264
+ function formatHandoffPairLabel(pair) {
100265
+ return `\`${pair.fromRole}\` → \`${pair.toRole}\``;
100266
+ }
100267
+ function formatHandoffTemplateCommand(command, pair, cliEnvPrefix = "", modeArg) {
100268
+ const modeFlag = modeArg === undefined ? "" : ` --mode="${modeArg}"`;
100269
+ return `${cliEnvPrefix}chatroom handoff ${command} --from="${pair.fromRole}" --to="${pair.toRole}"${modeFlag} --team-id="${pair.teamId}"`;
100270
+ }
100271
+ function missingPairMessage(command, missing) {
100272
+ return [
100273
+ `handoff ${command} requires both --from and --to (missing: ${missing}). Handoff templates are keyed by the (sender, recipient) pair.`,
100274
+ `Example: chatroom handoff ${command} --from="planner" --to="builder" --mode="code" --team-id="duo"`
100275
+ ].join(`
100276
+ `);
100277
+ }
100278
+ function missingModeMessage(command) {
100279
+ return [
100280
+ `handoff ${command} requires --mode (missing: --mode). Handoff templates are keyed by the (sender, recipient) pair and the conversation mode.`,
100281
+ `Example: chatroom handoff ${command} --from="planner" --to="user" --mode="chat" --team-id="duo"`
100282
+ ].join(`
100283
+ `);
100284
+ }
100285
+ function unknownModeMessage(mode) {
100286
+ return `Unknown mode "${mode}". Valid modes: ${CONVERSATION_MODES.join(", ")}.`;
100287
+ }
100288
+ function legacyRoleFlagsMessage(command, input) {
100289
+ const header = `handoff ${command} no longer accepts --role/--next-role. Handoff templates are keyed by the (sender, recipient) pair.`;
100290
+ const modeArg = input.mode ?? "<chat|code|code:enhanced>";
100291
+ if (input.legacyRole !== undefined && input.legacyNextRole !== undefined) {
100292
+ return [
100293
+ header,
100294
+ `Use: ${formatHandoffTemplateCommand(command, {
100295
+ teamId: input.teamId,
100296
+ fromRole: input.legacyRole,
100297
+ toRole: input.legacyNextRole
100298
+ }, "", modeArg)}`
100299
+ ].join(`
100300
+ `);
100301
+ }
100302
+ if (input.legacyRole !== undefined && input.rolePairs && input.rolePairs.length > 0) {
100303
+ return [
100304
+ header,
100305
+ `Pairs from "${input.legacyRole}" in team "${input.teamId}":`,
100306
+ ...input.rolePairs.map((pair) => ` ${formatHandoffTemplateCommand(command, pair, "", modeArg)}`)
100307
+ ].join(`
100308
+ `);
100309
+ }
100310
+ const to = input.legacyNextRole ?? "<recipient-role>";
100311
+ return [
100312
+ header,
100313
+ `Use: chatroom handoff ${command} --from="<your-role>" --to="${to}" --mode="${modeArg}" --team-id="${input.teamId}"`
100314
+ ].join(`
100315
+ `);
100316
+ }
100317
+ function unknownTeamMessage(team) {
100318
+ return `Unknown team "${team}". Known teams: ${TEAM_PRESET_IDS.join(", ")}.`;
100319
+ }
100320
+ function unknownFromRoleMessage(input) {
100321
+ return `Role "${input.from}" has no handoff templates in team "${input.team}". Roles with handoff templates: ${input.roles.join(", ")}.`;
100322
+ }
100323
+ function unknownPairMessage(input) {
100324
+ return `No handoff template for "${input.from}" → "${input.to}" in team "${input.team}". Valid recipients for "${input.from}": ${input.recipients.join(", ")}.`;
100325
+ }
100326
+ function unrenderablePairMessage(pair) {
100327
+ return `No handoff template for "${pair.fromRole}" → "${pair.toRole}" in team "${pair.teamId}".`;
100328
+ }
100329
+ var HandoffTemplatePairError, DEFAULT_HANDOFF_TEAM_ID = "duo";
100330
+ var init_pair = __esm(() => {
100331
+ init_conversation_mode();
100332
+ init_team_kind();
100333
+ HandoffTemplatePairError = class HandoffTemplatePairError extends Error {
100334
+ code;
100335
+ constructor(code2, message) {
100336
+ super(message);
100337
+ this.code = code2;
100338
+ this.name = "HandoffTemplatePairError";
100339
+ }
100340
+ };
100341
+ });
100342
+
100343
+ // ../../services/backend/prompts/native/handoff-visibility.ts
100344
+ function getHandoffRecipientVisibilityCallout(toRole) {
100345
+ const recipient = toRole.toLowerCase() === "user" ? "user" : `\`${toRole}\` agent`;
100346
+ const sendCommand = `\`handoff --next-role="${toRole}"\``;
100347
+ return `> ⚠️ **Template notice — not part of the message. Do not copy this notice into your handoff.**
100348
+ > Recipient visibility: the ${recipient} receives only the text inside your ${sendCommand} command${toRole.toLowerCase() === "user" ? ", plus any `notify-user` notices you sent earlier in this task" : ""}. It cannot see anything you write in this agent session${toRole.toLowerCase() === "user" ? " (including direct replies)" : ""}, or tool output. Put your complete deliverable in the handoff message.`;
100349
+ }
100350
+
100234
100351
  // ../../services/backend/prompts/cli/handoff/command.ts
100235
100352
  function handoffCommand(params) {
100236
100353
  const prefix = params.cliEnvPrefix || "";
@@ -100247,39 +100364,6 @@ var init_command2 = __esm(() => {
100247
100364
  init_stdin_heredoc();
100248
100365
  });
100249
100366
 
100250
- // ../../services/backend/prompts/native/handoff-visibility.ts
100251
- function getHandoffRecipientVisibilityCallout(toRole) {
100252
- if (toRole.toLowerCase() === "user") {
100253
- return `---
100254
-
100255
- ⚠️ **CRITICAL — Recipient visibility**
100256
-
100257
- The user receives the text inside your \`handoff --next-role="user"\` command, plus any \`notify-user\` notices you sent earlier in this task.
100258
-
100259
- They **cannot** see:
100260
- - Anything you write in this agent session (including direct replies like "Hello!")
100261
- - Tool output
100262
-
100263
- When you write this handoff, put your **complete** deliverable in the handoff message. Do not rely on session text or on earlier notices.
100264
-
100265
- ---`;
100266
- }
100267
- return `---
100268
-
100269
- ⚠️ **CRITICAL — Recipient visibility**
100270
-
100271
- The \`${toRole}\` agent **only** receives the text inside your \`handoff --next-role="${toRole}"\` command.
100272
-
100273
- They **cannot** see:
100274
- - Anything you write in this agent session
100275
- - \`notify-user\` notices (notices go to the user only)
100276
- - Tool output
100277
-
100278
- When you write this handoff, put your **complete** deliverable in the handoff message — not in session text.
100279
-
100280
- ---`;
100281
- }
100282
-
100283
100367
  // ../../services/backend/prompts/utils/file-reference-guidance.ts
100284
100368
  function getFileReferenceGuidanceComment() {
100285
100369
  return `<!-- File references (clickable in workspace UI): use repo-relative paths with a file extension — e.g. \`apps/webapp/src/modules/chatroom/foo.ts\` or [apps/webapp/src/foo.ts](apps/webapp/src/foo.ts). Avoid absolute paths, file:// prefixes, and paths without / or extension. -->`;
@@ -100290,9 +100374,6 @@ function getFileReferenceProofOfCompletionExample() {
100290
100374
  }
100291
100375
 
100292
100376
  // ../../services/backend/prompts/teams/architect-handoff-templates.ts
100293
- function normalizeEntryPointRole(entryPointRole) {
100294
- return entryPointRole.trim().toLowerCase() || "planner";
100295
- }
100296
100377
  function getArchitectFocus() {
100297
100378
  return "module boundaries, APIs, schemas, indexes and queries, invariants, failure and recovery handling, tests, and implementation sequence";
100298
100379
  }
@@ -100305,13 +100386,9 @@ function getArchitectRequirements() {
100305
100386
  - Account for Convex reactivity and bandwidth: query invalidation patterns, avoiding unnecessary reactive fanout, and separating high-frequency heartbeat/liveness/status fields from low-frequency identity/configuration fields.
100306
100387
  - Specify concrete schema, query, and mutation changes; migration/backfill sequence; tests; and verification order.`;
100307
100388
  }
100308
- function getEntryPointToArchitectHandoffTemplate(entryPointRole) {
100309
- const entryPoint = normalizeEntryPointRole(entryPointRole);
100310
- return `${getHandoffRecipientVisibilityCallout("architect")}
100311
-
100312
- ## Handoff Template (${entryPoint} → architect)
100313
-
100314
- The automatically injected \`<user-message>\` is the authoritative request. Add only concise context that the Architect needs to design within the existing repository and team scope.
100389
+ function getEntryPointToArchitectHandoffTemplate(query) {
100390
+ const entryPoint = query.fromRole;
100391
+ return `The automatically injected \`<user-message>\` is the authoritative request. Add only concise context that the Architect needs to design within the existing repository and team scope.
100315
100392
 
100316
100393
  Provide the request, relevant constraints, and the files or product surfaces that need inspection. Ask for one evidence-backed design focused on ${getArchitectFocus()}.
100317
100394
 
@@ -100326,20 +100403,10 @@ ${handoffCommand({
100326
100403
  })}
100327
100404
  \`\`\``;
100328
100405
  }
100329
- function getArchitectToEntryPointHandoffTemplate(entryPointRole) {
100330
- return renderArchitectToEntryPointHandoffTemplate(normalizeEntryPointRole(entryPointRole));
100331
- }
100332
- function getGenericArchitectToEntryPointHandoffTemplate() {
100333
- return renderArchitectToEntryPointHandoffTemplate("<entry-point-role>", true);
100334
- }
100335
- function renderArchitectToEntryPointHandoffTemplate(entryPoint, generic = false) {
100336
- const sharedContractsHeading = !generic && entryPoint === "planner" ? "## Shared contracts (planner-owned)" : "## Shared contracts (configured entry-point-owned)";
100337
- const placeholderInstruction = generic ? " Replace `<entry-point-role>` with the configured entry-point role before running it." : "";
100338
- return `${getHandoffRecipientVisibilityCallout(entryPoint)}
100339
-
100340
- ## Handoff Template (Architect → Entry Point)
100341
-
100342
- Return exactly one recommended, evidence-backed design brief for the authoritative user request to the configured entry point. This is an advisory handback: do not implement code, edit files, spawn subagents, present alternatives, or expand scope. The injected \`<handoff-templates>\` block is the authoritative structure for this handoff; complete every section in order. Use \`Not Applicable.\` only when a section is genuinely inapplicable, with no explanation or filler.
100406
+ function getArchitectToEntryPointHandoffTemplate(query) {
100407
+ const entryPoint = query.toRole;
100408
+ const sharedContractsHeading = `## Shared contracts (${entryPoint}-owned)`;
100409
+ return `Instructions (not part of the message): Return exactly one recommended, evidence-backed design brief for the authoritative user request to \`${entryPoint}\`. This is an advisory handback: do not implement code, edit files, spawn subagents, present alternatives, or expand scope. The injected \`<handoff-templates>\` block is the authoritative structure for this handoff; complete every section in order. Use \`Not Applicable.\` only when a section is genuinely inapplicable, with no explanation or filler.
100343
100410
 
100344
100411
  ## Summary
100345
100412
  <describe the design problem being solved, the repository/product surface where it fits, and the evidence-backed context; do not refer to hidden session text>
@@ -100387,7 +100454,7 @@ ${sharedContractsHeading}
100387
100454
  ## Requirements (acceptance criteria)
100388
100455
  - <one concrete, verifiable requirement per bullet; include exact data shape, API contract, migration result, and failure behavior>
100389
100456
  - Include repository test coverage for domain, concurrency, read-pattern, migration, and recovery risk areas.
100390
- - Verify the implemented user-facing entry point or task-delivery path end-to-end; unit tests alone are insufficient.
100457
+ - Verify the implemented user-facing feature or task-delivery path end-to-end; unit tests alone are insufficient.
100391
100458
 
100392
100459
  ## What to avoid
100393
100460
  - Do not implement code or edit files as the architect; this handoff is advisory only.
@@ -100401,8 +100468,7 @@ ${sharedContractsHeading}
100401
100468
  ## Out of scope
100402
100469
  - <explicit files, flows, behavior, or migration work the implementer must not touch>
100403
100470
 
100404
- ## Handoff
100405
- Run the normal handoff command to the configured entry point with this complete design, then stop.${placeholderInstruction}
100471
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100406
100472
 
100407
100473
  \`\`\`bash
100408
100474
  ${handoffCommand({
@@ -100417,145 +100483,162 @@ var init_architect_handoff_templates = __esm(() => {
100417
100483
  init_command2();
100418
100484
  });
100419
100485
 
100420
- // ../../services/backend/prompts/teams/uiux-engineer-handoff-templates.ts
100421
- function normalizeEntryPointRole2(entryPointRole) {
100422
- return entryPointRole.trim().toLowerCase() || "planner";
100423
- }
100424
- function getUiuxEngineerFocus() {
100425
- return "complete user flows, loading/empty/error/success states, component ownership, theme tokens and layout, responsive details, and UI tests";
100486
+ // ../../services/backend/prompts/teams/duo/handoff-templates/architect-planner-code.ts
100487
+ function getArchitectPlannerCodeTemplate(query) {
100488
+ return getArchitectToEntryPointHandoffTemplate(query);
100426
100489
  }
100427
- function getUiuxEngineerRequirements() {
100428
- return `
100429
- - Specify complete user flows with explicit loading, empty, error, success, disabled, and retry states where applicable.
100430
- - Define component hierarchy and ownership, props/state/events, data boundaries, and interaction behavior.
100431
- - Choose concrete existing ShadCN components with the Base UI backend and lucide-react/react-icons conventions; do not write "use an appropriate component."
100432
- - Specify Tailwind utility classes or semantic theme-token classes for layout, spacing, sizing, typography, states, responsive behavior, and dark mode.
100433
- - Provide the target HTML markup with exact class attributes and any required CSS/styles in the handoff.
100434
- - Specify responsive breakpoints/layout behavior, visual feedback, destructive-action safeguards, exact files/components, and the UI/integration test plan.
100435
- - Do not propose or require web accessibility implementation work unless the user explicitly requests it.`;
100436
- }
100437
- function getEntryPointToUiuxEngineerHandoffTemplate(entryPointRole) {
100438
- const entryPoint = normalizeEntryPointRole2(entryPointRole);
100439
- return `${getHandoffRecipientVisibilityCallout("uiux-engineer")}
100440
-
100441
- ## Handoff Template (${entryPoint} → uiux-engineer)
100442
-
100443
- The automatically injected \`<user-message>\` is the authoritative request. Add only concise context that the UI/UX Engineer needs to design within the existing repository and team scope.
100490
+ var init_architect_planner_code = __esm(() => {
100491
+ init_architect_handoff_templates();
100492
+ });
100444
100493
 
100445
- Provide the request, relevant constraints, and the files or product surfaces that need inspection. Ask for one evidence-backed design focused on ${getUiuxEngineerFocus()}.
100494
+ // ../../services/backend/prompts/teams/duo/handoff-templates/architect-planner-chat.ts
100495
+ var init_architect_planner_chat = __esm(() => {
100496
+ init_architect_planner_code();
100497
+ });
100446
100498
 
100447
- After completing the design, hand it back to \`${entryPoint}\` with the normal handoff command. Stop after the successful handoff; do not implement the design or delegate further work.
100499
+ // ../shared/src/domain/chatroom-role.ts
100500
+ var CHATROOM_ROLE_USER = "user";
100501
+ var init_chatroom_role = __esm(() => {
100502
+ init_agent_role();
100503
+ });
100448
100504
 
100449
- \`\`\`bash
100450
- ${handoffCommand({
100451
- chatroomId: "<chatroom-id>",
100452
- role: "uiux-engineer",
100453
- nextRole: entryPoint,
100454
- cliEnvPrefix: ""
100455
- })}
100456
- \`\`\``;
100505
+ // ../../services/backend/prompts/cli/handoff-templates/contracts.ts
100506
+ function handoffTemplateByMode(getters) {
100507
+ return (query) => query.conversationMode === "chat" ? getters.chat(query) : getters.code(query);
100508
+ }
100509
+ function validateRoleHandoffContracts(contracts) {
100510
+ const byRole = new Map;
100511
+ for (const contract of contracts) {
100512
+ const key = contract.role.toLowerCase();
100513
+ if (byRole.has(key)) {
100514
+ throw new Error(`Duplicate role handoff contract: "${contract.role}"`);
100515
+ }
100516
+ byRole.set(key, contract);
100517
+ }
100518
+ for (const contract of contracts) {
100519
+ const ownerKey = contract.role.toLowerCase();
100520
+ for (const target of Object.keys(contract.outboundTemplates)) {
100521
+ const targetKey = target.toLowerCase();
100522
+ if (targetKey === "user")
100523
+ continue;
100524
+ const targetContract = byRole.get(targetKey);
100525
+ if (!targetContract) {
100526
+ throw new Error(`Role "${contract.role}" declares an outbound template to "${target}", which is neither 'user' nor a role listed in the catalogue`);
100527
+ }
100528
+ const declaresOwner = (targetContract.receivesFrom ?? []).some((from) => from.toLowerCase() === ownerKey);
100529
+ if (!declaresOwner) {
100530
+ throw new Error(`Reciprocity failure: role "${targetContract.role}" receives from "${contract.role}" (via the ${contract.role} → ${target} template) but does not declare "${contract.role}" in receivesFrom`);
100531
+ }
100532
+ }
100533
+ }
100534
+ }
100535
+ function validateBuiltinOwners(teamName, expectedRoles, contracts) {
100536
+ const actualRoles = new Set;
100537
+ const byRole = new Map;
100538
+ for (const contract of contracts) {
100539
+ const normalizedOwner = contract.role.trim().toLowerCase();
100540
+ if (!normalizedOwner || contract.role !== normalizedOwner) {
100541
+ throw new Error(`${teamName} handoff owner "${contract.role}" is not canonical`);
100542
+ }
100543
+ if (actualRoles.has(normalizedOwner)) {
100544
+ throw new Error(`${teamName} has duplicate handoff contract owner "${contract.role}"`);
100545
+ }
100546
+ if (!expectedRoles.has(normalizedOwner)) {
100547
+ throw new Error(`${teamName} has unexpected handoff contract role "${contract.role}"`);
100548
+ }
100549
+ actualRoles.add(normalizedOwner);
100550
+ byRole.set(normalizedOwner, contract);
100551
+ }
100552
+ for (const role of expectedRoles) {
100553
+ if (!actualRoles.has(role)) {
100554
+ throw new Error(`${teamName} is missing handoff contract for role "${role}"`);
100555
+ }
100556
+ }
100557
+ return byRole;
100457
100558
  }
100458
- function getUiuxEngineerToEntryPointHandoffTemplate(entryPointRole) {
100459
- return renderUiuxEngineerToEntryPointHandoffTemplate(normalizeEntryPointRole2(entryPointRole));
100559
+ function validateReferenceTargets(teamName, owner, label, targets, allowedTargets) {
100560
+ const seen = new Set;
100561
+ for (const target of targets) {
100562
+ const normalizedTarget = target.trim().toLowerCase();
100563
+ if (target !== normalizedTarget || !allowedTargets.has(normalizedTarget)) {
100564
+ throw new Error(`${teamName} role "${owner}" has invalid ${label} target "${target}"`);
100565
+ }
100566
+ if (seen.has(normalizedTarget)) {
100567
+ throw new Error(`${teamName} role "${owner}" has duplicate ${label} target "${target}"`);
100568
+ }
100569
+ seen.add(normalizedTarget);
100570
+ }
100460
100571
  }
100461
- function getGenericUiuxEngineerToEntryPointHandoffTemplate() {
100462
- return renderUiuxEngineerToEntryPointHandoffTemplate("<entry-point-role>", true);
100572
+ function validateBuiltinReferences(teamName, allowedTargets, contracts) {
100573
+ for (const contract of contracts) {
100574
+ const owner = contract.role;
100575
+ validateReferenceTargets(teamName, owner, "receivesFrom", contract.receivesFrom, allowedTargets);
100576
+ validateReferenceTargets(teamName, owner, "returnsTo", contract.returnsTo, allowedTargets);
100577
+ const outboundTargets = Object.keys(contract.outboundTemplates);
100578
+ if (outboundTargets.length === 0) {
100579
+ throw new Error(`${teamName} role "${owner}" must have an outbound handoff capability`);
100580
+ }
100581
+ const returnsTo = new Set(contract.returnsTo);
100582
+ const outbound = new Set(outboundTargets);
100583
+ validateReferenceTargets(teamName, owner, "outbound", outboundTargets, allowedTargets);
100584
+ for (const target of outboundTargets) {
100585
+ if (typeof contract.outboundTemplates[target] !== "function") {
100586
+ throw new Error(`${teamName} role "${owner}" has no outbound getter for target "${target}"`);
100587
+ }
100588
+ }
100589
+ if (returnsTo.size !== outbound.size || [...returnsTo].some((target) => !outbound.has(target))) {
100590
+ throw new Error(`${teamName} role "${owner}" returnsTo targets must exactly match outbound targets`);
100591
+ }
100592
+ }
100463
100593
  }
100464
- function renderUiuxEngineerToEntryPointHandoffTemplate(entryPoint, generic = false) {
100465
- const sharedContractsHeading = !generic && entryPoint === "planner" ? "## Shared contracts (planner-owned)" : "## Shared contracts (configured entry-point-owned)";
100466
- const placeholderInstruction = generic ? " Replace `<entry-point-role>` with the configured entry-point role before running it." : "";
100467
- return `${getHandoffRecipientVisibilityCallout(entryPoint)}
100468
-
100469
- ## Handoff Template (UI/UX Engineer → Entry Point)
100470
-
100471
- Return exactly one recommended, evidence-backed design brief for the authoritative user request to the configured entry point. This is an advisory handback: do not implement code, edit files, spawn subagents, present alternatives, or expand scope. The injected \`<handoff-templates>\` block is the authoritative structure for this handoff; complete every section in order. Use \`Not Applicable.\` only when a section is genuinely inapplicable, with no explanation or filler.
100472
-
100473
- ## Summary
100474
- <describe the design problem being solved, the repository/product surface where it fits, and the evidence-backed context; do not refer to hidden session text>
100475
-
100476
- ## Goal
100477
- <state the one-sentence outcome this design delivers>
100478
-
100479
- ## Key Knowledge for High Quality Bar
100480
- <cite the inspected repository patterns and complete the UI/UX engineer checklist below; do not provide a high-level essay>
100481
- - Produce exactly one recommended design for ${getUiuxEngineerFocus()}.
100482
- - Name concrete repository paths, existing components/tokens, props/state/events, data boundaries, acceptance criteria, risks, and verification steps.
100483
- ${getUiuxEngineerRequirements()}
100484
-
100485
- ## Force Multipliers
100486
- <name the existing components, patterns, tokens, utilities, and platform conventions to reuse, and state why each reduces implementation risk or duplication>
100487
- - Keep the design within the repository's established source-of-truth boundaries and avoid introducing a new registry or abstraction without evidence.
100488
-
100489
- ## Files to implement (exhaustive, file-level)
100490
- List every file or product surface the implementer must create or modify. Mark each \`(Required)\` or \`(Optional)\`. For every file, give the exact responsibility, exported types/signatures/props, state/data/event boundaries, component hierarchy, and target Tailwind/theme-token snippet detailed enough to implement without guessing.
100491
- ${getFileReferenceGuidanceComment()}
100492
-
100493
- ### \`<repo-relative/path.ext>\` (Required)
100494
- **Change:** <precise add/modify/remove responsibility and why>
100495
-
100496
- \`\`\`text
100497
- // Target HTML markup, exact class attributes, and required CSS/styles.
100498
- // Include component hierarchy and props/state/events needed for implementation.
100499
- \`\`\`
100500
-
100501
- <add one block per file; do not collapse multiple files into a directory or vague layer>
100502
-
100503
- ${sharedContractsHeading}
100504
- <list cross-file interfaces, component/data contracts, state boundaries, or write exactly \`Not Applicable.\` when genuinely inapplicable>
100505
-
100506
- ### Interfaces & types
100507
- \`\`\`typescript
100508
- // Shared props, state, events, query shapes, or interaction contracts.
100509
- \`\`\`
100510
-
100511
- ### Reference snippets
100512
- \`\`\`tsx
100513
- // Canonical component imports, hook usage, or layout examples.
100514
- \`\`\`
100515
-
100516
- ## Requirements (acceptance criteria)
100517
- - <one concrete, verifiable requirement per bullet; include exact states, interactions, classes/tokens, and responsive behavior>
100518
- - Include UI and integration test coverage for the design's risk areas.
100519
- - Verify the implemented user-facing entry point end-to-end; unit tests alone are insufficient.
100520
-
100521
- ## What to avoid
100522
- - Do not implement code or edit files as the UI/UX engineer; this handoff is advisory only.
100523
- - Do not present alternative designs, generic advice, or requirements without concrete evidence and file-level consequences.
100524
- - Do not invent components, props, tokens, interaction behavior, or source-of-truth locations when existing repository patterns apply.
100525
- - <explicit task-specific anti-patterns, scope boundaries, and destructive-action/source-of-truth pitfalls>
100526
-
100527
- ## Skills to activate
100528
- - <relevant repository skills and why they apply, or write exactly \`Not Applicable.\` when none apply>
100529
-
100530
- ## Out of scope
100531
- - <explicit files, flows, behavior, or migration work the implementer must not touch>
100532
-
100533
- ## Handoff
100534
- Run the normal handoff command to the configured entry point with this complete design, then stop.${placeholderInstruction}
100535
-
100536
- \`\`\`bash
100537
- ${handoffCommand({
100538
- chatroomId: "<chatroom-id>",
100539
- role: "uiux-engineer",
100540
- nextRole: entryPoint,
100541
- cliEnvPrefix: ""
100542
- })}
100543
- \`\`\``;
100594
+ function validateBuiltinReciprocity(teamName, byRole, contracts) {
100595
+ for (const contract of contracts) {
100596
+ const owner = contract.role;
100597
+ for (const receivedFrom of contract.receivesFrom) {
100598
+ if (receivedFrom === CHATROOM_ROLE_USER)
100599
+ continue;
100600
+ const source = byRole.get(receivedFrom);
100601
+ if (!source?.outboundTemplates[owner]) {
100602
+ throw new Error(`${teamName} role "${owner}" receives from "${receivedFrom}" without a reverse outbound edge`);
100603
+ }
100604
+ }
100605
+ }
100606
+ try {
100607
+ validateRoleHandoffContracts(contracts);
100608
+ } catch (error51) {
100609
+ const contextualError = new Error(`${teamName}: ${error51 instanceof Error ? error51.message : String(error51)}`);
100610
+ Object.defineProperty(contextualError, "cause", { value: error51, configurable: true });
100611
+ throw contextualError;
100612
+ }
100544
100613
  }
100545
- var init_uiux_engineer_handoff_templates = __esm(() => {
100546
- init_command2();
100614
+ function validateBuiltinTeamRoleHandoffContracts(teamId, contracts) {
100615
+ const teamName = TEAM_PRESETS[teamId].name;
100616
+ const expectedRoles = new Set(TEAM_PRESETS[teamId].roles);
100617
+ const byRole = validateBuiltinOwners(teamName, expectedRoles, contracts);
100618
+ const allowedTargets = new Set([...expectedRoles, CHATROOM_ROLE_USER]);
100619
+ validateBuiltinReferences(teamName, allowedTargets, contracts);
100620
+ validateBuiltinReciprocity(teamName, byRole, contracts);
100621
+ }
100622
+ var init_contracts = __esm(() => {
100623
+ init_chatroom_role();
100624
+ init_team_presets();
100547
100625
  });
100548
100626
 
100549
100627
  // ../../services/backend/prompts/teams/duo/handoff-templates/architect.ts
100550
100628
  var duoArchitectHandoffContract;
100551
100629
  var init_architect = __esm(() => {
100552
- init_architect_handoff_templates();
100630
+ init_architect_planner_chat();
100631
+ init_architect_planner_code();
100632
+ init_contracts();
100553
100633
  duoArchitectHandoffContract = {
100554
100634
  role: "architect",
100555
100635
  receivesFrom: ["planner"],
100556
100636
  returnsTo: ["planner"],
100557
100637
  outboundTemplates: {
100558
- planner: () => getArchitectToEntryPointHandoffTemplate("planner")
100638
+ planner: handoffTemplateByMode({
100639
+ chat: getArchitectPlannerCodeTemplate,
100640
+ code: getArchitectPlannerCodeTemplate
100641
+ })
100559
100642
  }
100560
100643
  };
100561
100644
  });
@@ -100577,13 +100660,16 @@ var DELEGATION_BRIEF_DISCLOSURE_CHECKBOX = "- [ ] I confirm the delegation brief
100577
100660
  function getHandoffNotApplicableSectionComment(context3) {
100578
100661
  return `<!-- REQUIRED. ${context3}, or write exactly "${HANDOFF_NOT_APPLICABLE_EXACT_TEXT}" with no explanation. Do not omit this section. -->`;
100579
100662
  }
100580
- function getHandoffReportTemplateIntro(templateLabel) {
100581
- return `**${templateLabel}** — complete every section below. Do not omit sections, principles, or XML wrappers:
100663
+ function getHandoffTemplateTitleLine(pair) {
100664
+ return `Handoff template \`${pair.fromRole}\` → \`${pair.toRole}\` (copy only the body sections below; do not copy this line, the notice, or the instructions after the body):`;
100665
+ }
100666
+ function getHandoffReportTemplateIntro() {
100667
+ return `Instructions (not part of the message): complete every section below. Do not omit sections, principles, or XML wrappers.
100582
100668
 
100583
100669
  When a section has no content, write exactly \`${HANDOFF_NOT_APPLICABLE_EXACT_TEXT}\` — no explanation, no em-dash, no additional text.`;
100584
100670
  }
100585
100671
  function getDelegationBriefIntro() {
100586
- return `**Delegation Brief (Planner → Builder)** — paste into the handoff message. Include every field that applies. **Omit fields that do not apply** — do not write \`Not Applicable\` as filler.`;
100672
+ return `**Delegation Brief** — paste into the handoff message. Include every field that applies. **Omit fields that do not apply** — do not write \`Not Applicable\` as filler.`;
100587
100673
  }
100588
100674
  var HANDOFF_NOT_APPLICABLE_EXACT_TEXT = "Not Applicable.";
100589
100675
 
@@ -100657,11 +100743,9 @@ ${getRoleGuidanceDisclosureComment(params)}`;
100657
100743
  var ROLE_GUIDANCE_DISCLOSURE_CHECKBOX = "- [ ] I confirm that I've read and followed the role guidance before starting any work";
100658
100744
  var init_role_guidance_disclosure = () => {};
100659
100745
 
100660
- // ../../services/backend/prompts/teams/duo/handoff-templates/builder-to-planner.ts
100661
- function getBuilderToPlannerHandoffTemplate(roleGuidanceContext) {
100662
- return `${getHandoffRecipientVisibilityCallout("planner")}
100663
-
100664
- ${getHandoffReportTemplateIntro("Handoff Template (Builder → Planner)")}
100746
+ // ../../services/backend/prompts/teams/duo/handoff-templates/builder-planner-code.ts
100747
+ function getBuilderPlannerCodeBody(roleGuidanceContext) {
100748
+ return `${getHandoffReportTemplateIntro()}
100665
100749
 
100666
100750
  \`\`\`markdown
100667
100751
  ## Summary
@@ -100690,34 +100774,58 @@ ${getHandoffNotApplicableSectionComment("List review notes")}
100690
100774
  <specific areas for planner to check>
100691
100775
  \`\`\``;
100692
100776
  }
100693
- var init_builder_to_planner = __esm(() => {
100777
+ function getBuilderPlannerCodeTemplate(query) {
100778
+ return getBuilderPlannerCodeBody({
100779
+ chatroomId: query.chatroomId,
100780
+ role: query.role,
100781
+ cliEnvPrefix: query.cliEnvPrefix
100782
+ });
100783
+ }
100784
+ var init_builder_planner_code = __esm(() => {
100694
100785
  init_handoff_quality_principles();
100695
100786
  init_role_guidance_disclosure();
100696
100787
  });
100697
100788
 
100789
+ // ../../services/backend/prompts/teams/duo/handoff-templates/builder-planner-chat.ts
100790
+ var init_builder_planner_chat = __esm(() => {
100791
+ init_builder_planner_code();
100792
+ });
100793
+
100698
100794
  // ../../services/backend/prompts/teams/duo/handoff-templates/builder.ts
100699
100795
  var duoBuilderHandoffContract;
100700
100796
  var init_builder = __esm(() => {
100701
- init_builder_to_planner();
100797
+ init_builder_planner_chat();
100798
+ init_builder_planner_code();
100799
+ init_contracts();
100702
100800
  duoBuilderHandoffContract = {
100703
100801
  role: "builder",
100704
100802
  receivesFrom: ["planner"],
100705
100803
  returnsTo: ["planner"],
100706
100804
  outboundTemplates: {
100707
- planner: (query) => getBuilderToPlannerHandoffTemplate({
100708
- chatroomId: query.chatroomId,
100709
- role: query.role,
100710
- cliEnvPrefix: query.cliEnvPrefix
100805
+ planner: handoffTemplateByMode({
100806
+ chat: getBuilderPlannerCodeTemplate,
100807
+ code: getBuilderPlannerCodeTemplate
100711
100808
  })
100712
100809
  }
100713
100810
  };
100714
100811
  });
100715
100812
 
100716
- // ../../services/backend/prompts/teams/duo/handoff-templates/planner-to-builder.ts
100717
- function getPlannerToBuilderHandoffTemplate() {
100718
- return `${getHandoffRecipientVisibilityCallout("builder")}
100813
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-architect-code.ts
100814
+ function getPlannerArchitectCodeTemplate(query) {
100815
+ return getEntryPointToArchitectHandoffTemplate(query);
100816
+ }
100817
+ var init_planner_architect_code = __esm(() => {
100818
+ init_architect_handoff_templates();
100819
+ });
100719
100820
 
100720
- ${getDelegationBriefIntro()}
100821
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-architect-chat.ts
100822
+ var init_planner_architect_chat = __esm(() => {
100823
+ init_planner_architect_code();
100824
+ });
100825
+
100826
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-builder-code.ts
100827
+ function getPlannerBuilderCodeBody() {
100828
+ return `${getDelegationBriefIntro()}
100721
100829
 
100722
100830
  **Before you delegate:** if this slice introduces anything not yet grounded in the repository (a new library, API, external platform behavior, or an unresolved design choice), hand off to \`researcher\` first and delegate only after its brief returns. Skip this for small, well-understood edits. The \`researcher\` handoff template defines the criteria.
100723
100831
 
@@ -100727,7 +100835,9 @@ ${getDelegationBriefIntro()}
100727
100835
 
100728
100836
  **Detail bar:** Specify down to **every file** the builder will create or modify (full repo paths). Include code snippets — types, signatures, stubs, or target implementations — until a competent builder **cannot misinterpret** what to write. Vague layers ("update the backend", "fix the component") are not acceptable.
100729
100837
 
100730
- \`\`\`markdown
100838
+ Guidance for you (not part of the message): Keep one slice ≈ one focused review surface. Delegate slices incrementally — one at a time, not all at once.
100839
+
100840
+ \`\`\`\`markdown
100731
100841
  ## Summary
100732
100842
  <brief context for this delegation slice — what problem it solves and where it fits in the larger task>
100733
100843
 
@@ -100784,14 +100894,380 @@ Cross-file types, interfaces, or patterns that apply beyond a single file. Omit
100784
100894
  - <e.g. "Do not add new abstractions", "Do not refactor unrelated files", "Do not change existing public APIs">
100785
100895
 
100786
100896
  ## Skills to activate
100787
- - <e.g. chatroom skill activate code-review --chatroom-id=<id> --role=builder>
100897
+ - e.g. \`chatroom skill activate code-review --chatroom-id=<id> --role=builder\`
100788
100898
 
100789
100899
  ## Out of scope
100790
100900
  - <files or areas the builder must NOT touch in this slice>
100791
100901
 
100792
- Keep one slice ≈ one focused review surface. Delegate slices incrementally — one at a time, not all at once.`;
100902
+ \`\`\`\``;
100903
+ }
100904
+ function getPlannerBuilderCodeTemplate(_query) {
100905
+ return getPlannerBuilderCodeBody();
100906
+ }
100907
+ var init_planner_builder_code = () => {};
100908
+
100909
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-builder-chat.ts
100910
+ var init_planner_builder_chat = __esm(() => {
100911
+ init_planner_builder_code();
100912
+ });
100913
+
100914
+ // ../../services/backend/prompts/teams/researcher-handoff-templates.ts
100915
+ function getEntryPointToResearcherHandoffTemplate(query) {
100916
+ const entryPoint = query.fromRole;
100917
+ return `The automatically injected \`<user-message>\` is the authoritative request. Pass the decisions the research must ground, the specific research questions, known constraints, and the files or areas already suspected. Ask the researcher for a report only: do not edit files, implement code, or design alternative architectures.
100918
+
100919
+ ### When to research
100920
+
100921
+ Research before delegating when the slice introduces something not already grounded in this repository:
100922
+ - a new library, API, external service, platform behavior, or version-sensitive dependency;
100923
+ - an unfamiliar subsystem;
100924
+ - a change with several plausible designs;
100925
+ - any ambiguity the user has not resolved.
100926
+
100927
+ Skip research when the change is a small, well-understood edit in code you have already inspected.
100928
+
100929
+ After completing the research, the researcher must return the evidence-backed brief to \`${entryPoint}\` with the normal handoff command.
100930
+
100931
+ \`\`\`bash
100932
+ ${handoffCommand({
100933
+ chatroomId: "<chatroom-id>",
100934
+ role: entryPoint,
100935
+ nextRole: "researcher",
100936
+ cliEnvPrefix: ""
100937
+ })}
100938
+ \`\`\``;
100939
+ }
100940
+ function getResearcherToEntryPointHandoffTemplate(query) {
100941
+ const entryPoint = query.toRole;
100942
+ return `Instructions (not part of the message): Return a complete, evidence-backed research brief for the authoritative request. The researcher is advisory: do not edit files, implement code, or present alternative architectures beyond what grounds the decision. Answer only the questions asked. Separate every finding into confirmed (with evidence), inferred (with reasoning), or unknown. Never present a guess as fact. External claims must cite the source URL together with the version or date checked. Use the exact sections below, in this order.
100943
+
100944
+ ## Summary
100945
+ <state the answer to the core question in two to four sentences and whether any decision remains open>
100946
+
100947
+ ## Research questions
100948
+ <list each question exactly as asked or as derived from the request, numbered>
100949
+
100950
+ ## Answers
100951
+ <one entry per question, each tagged \`confirmed\` (with evidence), \`inferred\` (with reasoning), or \`unknown\`>
100952
+
100953
+ ## Repository evidence
100954
+ <concrete repository paths and symbols with what each shows; quote the relevant lines briefly>
100955
+
100956
+ ## External sources
100957
+ <URL, version or date checked, and the specific claim each source supports; write exactly \`None consulted.\` if no external source was needed, and say why>
100958
+
100959
+ ## Grounded facts for the plan
100960
+ <the facts the planner can rely on when decomposing and delegating, each tagged confirmed or inferred>
100961
+
100962
+ ## Remaining ambiguity
100963
+ <each open decision, who must decide it, and a recommended default; write exactly \`None observed.\` if none remain>
100964
+
100965
+ ## Risks and constraints
100966
+ <constraints from the repository or external platform, and risks the plan must account for>
100967
+
100968
+ ## Work completed
100969
+ <paths inspected, searches run, and sources opened, with the result of each>
100970
+
100971
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100972
+
100973
+ \`\`\`bash
100974
+ ${handoffCommand({
100975
+ chatroomId: "<chatroom-id>",
100976
+ role: "researcher",
100977
+ nextRole: entryPoint,
100978
+ cliEnvPrefix: ""
100979
+ })}
100980
+ \`\`\``;
100981
+ }
100982
+ var init_researcher_handoff_templates = __esm(() => {
100983
+ init_command2();
100984
+ });
100985
+
100986
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-researcher-code.ts
100987
+ function getPlannerResearcherCodeTemplate(query) {
100988
+ return getEntryPointToResearcherHandoffTemplate(query);
100989
+ }
100990
+ var init_planner_researcher_code = __esm(() => {
100991
+ init_researcher_handoff_templates();
100992
+ });
100993
+
100994
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-researcher-chat.ts
100995
+ var init_planner_researcher_chat = __esm(() => {
100996
+ init_planner_researcher_code();
100997
+ });
100998
+
100999
+ // ../../services/backend/prompts/teams/reviewer-handoff-templates.ts
101000
+ function getEntryPointToReviewerHandoffTemplate(query) {
101001
+ const entryPoint = query.fromRole;
101002
+ return `Pass the review target and the review focus. State the exact commit range, branch, pull request, or file list to inspect, the focus areas (for example security, correctness, or test quality), and any known context or constraints. Ask the reviewer for a report only: do not edit files, run builds or tests, or implement fixes.
101003
+
101004
+ ### When to review
101005
+
101006
+ Review before delivery for code-producing work:
101007
+ - a builder slice has just completed and is about to be delivered;
101008
+ - the user asks for a code review;
101009
+ - a change is large, risky, or touches security-sensitive or shared code.
101010
+
101011
+ Skip review for a trivial edit that has already been verified.
101012
+
101013
+ After completing the review, the reviewer must return its issue report to \`${entryPoint}\` with the normal handoff command.
101014
+
101015
+ \`\`\`bash
101016
+ ${handoffCommand({
101017
+ chatroomId: "<chatroom-id>",
101018
+ role: entryPoint,
101019
+ nextRole: "reviewer",
101020
+ cliEnvPrefix: ""
101021
+ })}
101022
+ \`\`\``;
101023
+ }
101024
+ function getReviewerToEntryPointHandoffTemplate(query) {
101025
+ const entryPoint = query.toRole;
101026
+ return `Instructions (not part of the message): Return a complete review report for the target the planner named. The reviewer is advisory: do not edit files, implement fixes, run builds or tests, or propose architecture rewrites beyond each issue's suggested fix. Report only what you observed and mark anything unverified as such. Label every issue with a severity: \`blocker\`, \`major\`, \`minor\`, or \`nit\`. Group the issues by severity with blockers first, and cite the repository-relative file and line or line range for each. Use the exact sections below, in this order.
101027
+
101028
+ ## Summary
101029
+ <one to three sentences: overall state of the target and the count of blocker/major issues>
101030
+
101031
+ ## Review scope
101032
+ <commits, paths, and PR/branch inspected; commands run, if any>
101033
+
101034
+ ## Issues
101035
+ <numbered list grouped by severity (blocker, major, minor, nit); each item: \`file:line\` — summary — evidence — suggested fix; write exactly \`None observed.\` if none>
101036
+
101037
+ ## Not reviewed
101038
+ <anything out of scope or unreadable; write exactly \`None.\` if none>
101039
+
101040
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
101041
+
101042
+ \`\`\`bash
101043
+ ${handoffCommand({
101044
+ chatroomId: "<chatroom-id>",
101045
+ role: "reviewer",
101046
+ nextRole: entryPoint,
101047
+ cliEnvPrefix: ""
101048
+ })}
101049
+ \`\`\``;
101050
+ }
101051
+ var init_reviewer_handoff_templates = __esm(() => {
101052
+ init_command2();
101053
+ });
101054
+
101055
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-reviewer-code.ts
101056
+ function getPlannerReviewerCodeTemplate(query) {
101057
+ return getEntryPointToReviewerHandoffTemplate(query);
101058
+ }
101059
+ var init_planner_reviewer_code = __esm(() => {
101060
+ init_reviewer_handoff_templates();
101061
+ });
101062
+
101063
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-reviewer-chat.ts
101064
+ var init_planner_reviewer_chat = __esm(() => {
101065
+ init_planner_reviewer_code();
101066
+ });
101067
+
101068
+ // ../../services/backend/prompts/teams/triage-handoff-templates.ts
101069
+ function getEntryPointToTriageHandoffTemplate(query) {
101070
+ const entryPoint = query.fromRole;
101071
+ return `The automatically injected \`<user-message>\` is the authoritative request. Pass the reported bug, observed and expected behavior, reproduction details and commands, relevant constraints, and the files or symbols already suspected. Ask triage to investigate and report only. Triage may inspect code and attempt a focused automated regression test as evidence, but must not edit implementation files or implement a fix.
101072
+
101073
+ After completing the investigation, triage must return the evidence-backed report to \`${entryPoint}\` with the normal handoff command.
101074
+
101075
+ \`\`\`bash
101076
+ ${handoffCommand({
101077
+ chatroomId: "<chatroom-id>",
101078
+ role: entryPoint,
101079
+ nextRole: "triage",
101080
+ cliEnvPrefix: ""
101081
+ })}
101082
+ \`\`\``;
101083
+ }
101084
+ function getTriageToEntryPointHandoffTemplate(query) {
101085
+ const entryPoint = query.toRole;
101086
+ return `Instructions (not part of the message): Return a complete, evidence-backed investigation of the authoritative reported bug. Triage is advisory: do not edit implementation files or implement the proposed fix. Begin with the \`## Summary\` section, then use the remaining sections below in order. Use \`###\` for sub-items within a section. Cite concrete repository paths and symbols, observed behavior, commands, and test output. Distinguish confirmed findings from hypotheses; never claim a test proved behavior unless its failing assertion demonstrates the report.
101087
+
101088
+ ## Summary
101089
+ <briefly state the diagnosis and whether the root cause was confirmed or remains a hypothesis>
101090
+
101091
+ ## Reported behavior
101092
+ <state the reported symptoms and expected behavior, including reproduction details and constraints recovered from the request or relevant history>
101093
+
101094
+ ## Root cause
101095
+ <trace the relevant ownership, data, and control flow using concrete repository paths and symbols; explain the causal reasoning and explicitly label the finding as confirmed or a hypothesis>
101096
+
101097
+ ## Reproduction attempt
101098
+ <give the focused test path and exact command, the failing assertion or exact blocker, and the outcome; if reproduction was blocked, state what was tried and what additional information would help; do not fabricate proof>
101099
+
101100
+ ## Proposed immediate fix
101101
+ <recommend the smallest appropriate change, naming the likely files and the specific change; do not implement it>
101102
+
101103
+ ## Systemic issues
101104
+ <list each separate systemic concern with repository evidence, impact, and follow-up concern, or write exactly: None observed.>
101105
+
101106
+ ## Work completed
101107
+ <state the code paths inspected and every test or reproduction action taken, including results>
101108
+
101109
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
101110
+
101111
+ \`\`\`bash
101112
+ ${handoffCommand({
101113
+ chatroomId: "<chatroom-id>",
101114
+ role: "triage",
101115
+ nextRole: entryPoint,
101116
+ cliEnvPrefix: ""
101117
+ })}
101118
+ \`\`\``;
101119
+ }
101120
+ var init_triage_handoff_templates = __esm(() => {
101121
+ init_command2();
101122
+ });
101123
+
101124
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-triage-code.ts
101125
+ function getPlannerTriageCodeTemplate(query) {
101126
+ return getEntryPointToTriageHandoffTemplate(query);
101127
+ }
101128
+ var init_planner_triage_code = __esm(() => {
101129
+ init_triage_handoff_templates();
101130
+ });
101131
+
101132
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-triage-chat.ts
101133
+ var init_planner_triage_chat = __esm(() => {
101134
+ init_planner_triage_code();
101135
+ });
101136
+
101137
+ // ../../services/backend/prompts/teams/uiux-engineer-handoff-templates.ts
101138
+ function getUiuxEngineerFocus() {
101139
+ return "complete user flows, loading/empty/error/success states, component ownership, theme tokens and layout, responsive details, and UI tests";
101140
+ }
101141
+ function getUiuxEngineerRequirements() {
101142
+ return `
101143
+ - Specify complete user flows with explicit loading, empty, error, success, disabled, and retry states where applicable.
101144
+ - Define component hierarchy and ownership, props/state/events, data boundaries, and interaction behavior.
101145
+ - Choose concrete existing ShadCN components with the Base UI backend and lucide-react/react-icons conventions; do not write "use an appropriate component."
101146
+ - Specify Tailwind utility classes or semantic theme-token classes for layout, spacing, sizing, typography, states, responsive behavior, and dark mode.
101147
+ - Provide the target HTML markup with exact class attributes and any required CSS/styles in the handoff.
101148
+ - Specify responsive breakpoints/layout behavior, visual feedback, destructive-action safeguards, exact files/components, and the UI/integration test plan.
101149
+ - Do not propose or require web accessibility implementation work unless the user explicitly requests it.`;
101150
+ }
101151
+ function getEntryPointToUiuxEngineerHandoffTemplate(query) {
101152
+ const entryPoint = query.fromRole;
101153
+ return `The automatically injected \`<user-message>\` is the authoritative request. Add only concise context that the UI/UX Engineer needs to design within the existing repository and team scope.
101154
+
101155
+ Provide the request, relevant constraints, and the files or product surfaces that need inspection. Ask for one evidence-backed design focused on ${getUiuxEngineerFocus()}.
101156
+
101157
+ After completing the design, hand it back to \`${entryPoint}\` with the normal handoff command. Stop after the successful handoff; do not implement the design or delegate further work.
101158
+
101159
+ \`\`\`bash
101160
+ ${handoffCommand({
101161
+ chatroomId: "<chatroom-id>",
101162
+ role: "uiux-engineer",
101163
+ nextRole: entryPoint,
101164
+ cliEnvPrefix: ""
101165
+ })}
101166
+ \`\`\``;
100793
101167
  }
100794
- var init_planner_to_builder = () => {};
101168
+ function getUiuxEngineerToEntryPointHandoffTemplate(query) {
101169
+ const entryPoint = query.toRole;
101170
+ const sharedContractsHeading = `## Shared contracts (${entryPoint}-owned)`;
101171
+ return `Instructions (not part of the message): Return exactly one recommended, evidence-backed design brief for the authoritative user request to \`${entryPoint}\`. This is an advisory handback: do not implement code, edit files, spawn subagents, present alternatives, or expand scope. The injected \`<handoff-templates>\` block is the authoritative structure for this handoff; complete every section in order. Use \`Not Applicable.\` only when a section is genuinely inapplicable, with no explanation or filler.
101172
+
101173
+ ## Summary
101174
+ <describe the design problem being solved, the repository/product surface where it fits, and the evidence-backed context; do not refer to hidden session text>
101175
+
101176
+ ## Goal
101177
+ <state the one-sentence outcome this design delivers>
101178
+
101179
+ ## Key Knowledge for High Quality Bar
101180
+ <cite the inspected repository patterns and complete the UI/UX engineer checklist below; do not provide a high-level essay>
101181
+ - Produce exactly one recommended design for ${getUiuxEngineerFocus()}.
101182
+ - Name concrete repository paths, existing components/tokens, props/state/events, data boundaries, acceptance criteria, risks, and verification steps.
101183
+ ${getUiuxEngineerRequirements()}
101184
+
101185
+ ## Force Multipliers
101186
+ <name the existing components, patterns, tokens, utilities, and platform conventions to reuse, and state why each reduces implementation risk or duplication>
101187
+ - Keep the design within the repository's established source-of-truth boundaries and avoid introducing a new registry or abstraction without evidence.
101188
+
101189
+ ## Files to implement (exhaustive, file-level)
101190
+ List every file or product surface the implementer must create or modify. Mark each \`(Required)\` or \`(Optional)\`. For every file, give the exact responsibility, exported types/signatures/props, state/data/event boundaries, component hierarchy, and target Tailwind/theme-token snippet detailed enough to implement without guessing.
101191
+ ${getFileReferenceGuidanceComment()}
101192
+
101193
+ ### \`<repo-relative/path.ext>\` (Required)
101194
+ **Change:** <precise add/modify/remove responsibility and why>
101195
+
101196
+ \`\`\`text
101197
+ // Target HTML markup, exact class attributes, and required CSS/styles.
101198
+ // Include component hierarchy and props/state/events needed for implementation.
101199
+ \`\`\`
101200
+
101201
+ <add one block per file; do not collapse multiple files into a directory or vague layer>
101202
+
101203
+ ${sharedContractsHeading}
101204
+ <list cross-file interfaces, component/data contracts, state boundaries, or write exactly \`Not Applicable.\` when genuinely inapplicable>
101205
+
101206
+ ### Interfaces & types
101207
+ \`\`\`typescript
101208
+ // Shared props, state, events, query shapes, or interaction contracts.
101209
+ \`\`\`
101210
+
101211
+ ### Reference snippets
101212
+ \`\`\`tsx
101213
+ // Canonical component imports, hook usage, or layout examples.
101214
+ \`\`\`
101215
+
101216
+ ## Requirements (acceptance criteria)
101217
+ - <one concrete, verifiable requirement per bullet; include exact states, interactions, classes/tokens, and responsive behavior>
101218
+ - Include UI and integration test coverage for the design's risk areas.
101219
+ - Verify the implemented user-facing feature end-to-end; unit tests alone are insufficient.
101220
+
101221
+ ## What to avoid
101222
+ - Do not implement code or edit files as the UI/UX engineer; this handoff is advisory only.
101223
+ - Do not present alternative designs, generic advice, or requirements without concrete evidence and file-level consequences.
101224
+ - Do not invent components, props, tokens, interaction behavior, or source-of-truth locations when existing repository patterns apply.
101225
+ - <explicit task-specific anti-patterns, scope boundaries, and destructive-action/source-of-truth pitfalls>
101226
+
101227
+ ## Skills to activate
101228
+ - <relevant repository skills and why they apply, or write exactly \`Not Applicable.\` when none apply>
101229
+
101230
+ ## Out of scope
101231
+ - <explicit files, flows, behavior, or migration work the implementer must not touch>
101232
+
101233
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
101234
+
101235
+ \`\`\`bash
101236
+ ${handoffCommand({
101237
+ chatroomId: "<chatroom-id>",
101238
+ role: "uiux-engineer",
101239
+ nextRole: entryPoint,
101240
+ cliEnvPrefix: ""
101241
+ })}
101242
+ \`\`\``;
101243
+ }
101244
+ var init_uiux_engineer_handoff_templates = __esm(() => {
101245
+ init_command2();
101246
+ });
101247
+
101248
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-uiux-engineer-code.ts
101249
+ function getPlannerUiuxEngineerCodeTemplate(query) {
101250
+ return getEntryPointToUiuxEngineerHandoffTemplate(query);
101251
+ }
101252
+ var init_planner_uiux_engineer_code = __esm(() => {
101253
+ init_uiux_engineer_handoff_templates();
101254
+ });
101255
+
101256
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-uiux-engineer-chat.ts
101257
+ var init_planner_uiux_engineer_chat = __esm(() => {
101258
+ init_planner_uiux_engineer_code();
101259
+ });
101260
+
101261
+ // ../../services/backend/prompts/utils/chat-handoff-template.ts
101262
+ function getChatToUserHandoffTemplate() {
101263
+ return `Instructions (not part of the message): chat response —
101264
+ \`\`\`markdown
101265
+ <write only the concise response the user should see; do not add handoff XML sections, proofs, context evidence, or placeholder text>
101266
+ \`\`\``;
101267
+ }
101268
+
101269
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-user-chat.ts
101270
+ var init_planner_user_chat = () => {};
100795
101271
 
100796
101272
  // ../../services/backend/prompts/utils/context-disclosure.ts
100797
101273
  function getContextReadDisclosureComment(params = {}) {
@@ -100814,16 +101290,9 @@ function getHandoffSeverityGuidanceBlock() {
100814
101290
  }
100815
101291
 
100816
101292
  // ../../services/backend/prompts/teams/verifier-handoff-templates.ts
100817
- function normalizeEntryPointRole3(entryPointRole) {
100818
- return entryPointRole.trim().toLowerCase() || "planner";
100819
- }
100820
- function getEntryPointToVerifierHandoffTemplate(entryPointRole) {
100821
- const entryPoint = normalizeEntryPointRole3(entryPointRole);
100822
- return `${getHandoffRecipientVisibilityCallout("verifier")}
100823
-
100824
- ## Handoff Template (${entryPoint} → verifier)
100825
-
100826
- The verifier judges, from chatroom logs only, whether the user's last message was achieved. It ${VERIFIER_TEST_RULE}; list any user-requested tests under Requested test runs. Treat the claimed outcome as a claim, not as evidence: the verifier does not trust it and checks every requirement against the logs themselves. Request this review only when the task involved code changes, in any conversation mode. The verdict returns to \`${entryPoint}\`.
101293
+ function getEntryPointToVerifierHandoffTemplate(query) {
101294
+ const entryPoint = query.fromRole;
101295
+ return `Instructions (not part of the message): The verifier judges, from chatroom logs only, whether the user's last message was achieved. It ${VERIFIER_TEST_RULE}; list any user-requested tests under Requested test runs. Treat the claimed outcome as a claim, not as evidence: the verifier does not trust it and checks every requirement against the logs themselves. Request this review only when the task involved code changes, in any conversation mode. The verdict returns to \`${entryPoint}\`.
100827
101296
 
100828
101297
  ## Round
100829
101298
  <1 or 2; for 2, cite the round-1 verdict message id>
@@ -100849,8 +101318,7 @@ The verifier judges, from chatroom logs only, whether the user's last message wa
100849
101318
  ## Known gaps
100850
101319
  <anything incomplete, or exactly \`None.\`>
100851
101320
 
100852
- ## Handoff
100853
- Send this request to the verifier with the command below, then stop. The verdict returns to \`${entryPoint}\`.
101321
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100854
101322
 
100855
101323
  \`\`\`bash
100856
101324
  ${handoffCommand({
@@ -100861,13 +101329,9 @@ ${handoffCommand({
100861
101329
  })}
100862
101330
  \`\`\``;
100863
101331
  }
100864
- function getVerifierToEntryPointHandoffTemplate(entryPointRole) {
100865
- const entryPoint = normalizeEntryPointRole3(entryPointRole);
100866
- return `${getHandoffRecipientVisibilityCallout(entryPoint)}
100867
-
100868
- ## Handoff Template (Verifier → ${entryPoint})
100869
-
100870
- Return one advisory verdict for the authoritative request. This review is non-binding: it uses chatroom logs, plus the requested test runs listed in the request, if any, deciding every requirement from the evidence those logs and runs actually contain. It also checks the work against the user's expectations (\`## User Expectations\`) under the same logs-only, claim-is-not-evidence rule. It ${VERIFIER_TEST_RULE}. Never accept the claimed outcome as proof. Use the exact sections below, in this order.
101332
+ function getVerifierToEntryPointHandoffTemplate(query) {
101333
+ const entryPoint = query.toRole;
101334
+ return `Instructions (not part of the message): Return one advisory verdict for the authoritative request. This review is non-binding: it uses chatroom logs, plus the requested test runs listed in the request, if any, deciding every requirement from the evidence those logs and runs actually contain. It also checks the work against the user's expectations (\`## User Expectations\`) under the same logs-only, claim-is-not-evidence rule. It ${VERIFIER_TEST_RULE}. Never accept the claimed outcome as proof. Use the exact sections below, in this order.
100871
101335
 
100872
101336
  ## Verdict
100873
101337
  <exactly one of ${VERIFIER_VERDICTS.join(", ")} as the value; ${ACHIEVED} only if every requirement and user expectation is met; ${NOT_ACHIEVED} if any requirement or user expectation is unmet (logs show it was not done, or contradict it); ${INCONCLUSIVE} if none is unmet but any is unverified (logs are silent)>
@@ -100890,8 +101354,7 @@ Return one advisory verdict for the authoritative request. This review is non-bi
100890
101354
  ## Scope and limits
100891
101355
  <state the test runs the verifier executed (command and exit result), or "No tests were run; none were requested."; log range read; whether the download was truncated; context id read and whether it matched the request>
100892
101356
 
100893
- ## Handoff
100894
- Run the normal handoff command to \`${entryPoint}\` with this complete verdict, then stop.
101357
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100895
101358
 
100896
101359
  \`\`\`bash
100897
101360
  ${handoffCommand({
@@ -101067,195 +101530,51 @@ var init_handoff_report_template_body = __esm(() => {
101067
101530
  init_unresolved_decisions();
101068
101531
  });
101069
101532
 
101070
- // ../../services/backend/prompts/teams/duo/handoff-templates/planner-to-user.ts
101071
- function getPlannerToUserReportTemplate(roleGuidanceContext) {
101072
- return `${getHandoffRecipientVisibilityCallout("user")}
101073
-
101074
- ${getHandoffReportTemplateIntro("Report Template (Planner → User)")}
101533
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-user-code.ts
101534
+ function getPlannerUserCodeTemplate(roleGuidanceContext) {
101535
+ return `${getHandoffReportTemplateIntro()}
101075
101536
 
101076
101537
  \`\`\`markdown
101077
101538
  ${getHandoffReportTemplateBody(roleGuidanceContext, { includeProofOfVerification: true })}
101078
101539
  \`\`\``;
101079
101540
  }
101080
- var init_planner_to_user = __esm(() => {
101541
+ var init_planner_user_code = __esm(() => {
101081
101542
  init_handoff_report_template_body();
101082
101543
  });
101083
101544
 
101084
- // ../../services/backend/prompts/utils/chat-handoff-template.ts
101085
- function getChatToUserHandoffTemplate() {
101086
- return `${getHandoffRecipientVisibilityCallout("user")}
101087
-
101088
- **Chat Response Template**
101089
-
101090
- \`\`\`markdown
101091
- <write only the concise response the user should see; do not add handoff XML sections, proofs, context evidence, or placeholder text>
101092
- \`\`\``;
101093
- }
101094
- var init_chat_handoff_template = () => {};
101095
-
101096
- // ../../services/backend/prompts/teams/researcher-handoff-templates.ts
101097
- function normalizeEntryPointRole4(entryPointRole) {
101098
- return entryPointRole.trim().toLowerCase() || "planner";
101099
- }
101100
- function getEntryPointToResearcherHandoffTemplate(entryPointRole) {
101101
- const entryPoint = normalizeEntryPointRole4(entryPointRole);
101102
- return `${getHandoffRecipientVisibilityCallout("researcher")}
101103
-
101104
- ## Handoff Template (${entryPoint} → researcher)
101105
-
101106
- The automatically injected \`<user-message>\` is the authoritative request. Pass the decisions the research must ground, the specific research questions, known constraints, and the files or areas already suspected. Ask the researcher for a report only: do not edit files, implement code, or design alternative architectures.
101107
-
101108
- ### When to research
101109
-
101110
- Research before delegating when the slice introduces something not already grounded in this repository:
101111
- - a new library, API, external service, platform behavior, or version-sensitive dependency;
101112
- - an unfamiliar subsystem;
101113
- - a change with several plausible designs;
101114
- - any ambiguity the user has not resolved.
101115
-
101116
- Skip research when the change is a small, well-understood edit in code you have already inspected.
101117
-
101118
- After completing the research, the researcher must return the evidence-backed brief to \`${entryPoint}\` with the normal handoff command.
101119
-
101120
- \`\`\`bash
101121
- ${handoffCommand({
101122
- chatroomId: "<chatroom-id>",
101123
- role: entryPoint,
101124
- nextRole: "researcher",
101125
- cliEnvPrefix: ""
101126
- })}
101127
- \`\`\``;
101545
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-verifier-code.ts
101546
+ function getPlannerVerifierCodeTemplate(query) {
101547
+ return getEntryPointToVerifierHandoffTemplate(query);
101128
101548
  }
101129
- function getResearcherToEntryPointHandoffTemplate(entryPointRole) {
101130
- const entryPoint = normalizeEntryPointRole4(entryPointRole);
101131
- return `${getHandoffRecipientVisibilityCallout(entryPoint)}
101132
-
101133
- ## Handoff Template (Researcher → ${entryPoint})
101134
-
101135
- Return a complete, evidence-backed research brief for the authoritative request. The researcher is advisory: do not edit files, implement code, or present alternative architectures beyond what grounds the decision. Answer only the questions asked. Separate every finding into confirmed (with evidence), inferred (with reasoning), or unknown. Never present a guess as fact. External claims must cite the source URL together with the version or date checked. Use the exact sections below, in this order.
101136
-
101137
- ## Summary
101138
- <state the answer to the core question in two to four sentences and whether any decision remains open>
101139
-
101140
- ## Research questions
101141
- <list each question exactly as asked or as derived from the request, numbered>
101142
-
101143
- ## Answers
101144
- <one entry per question, each tagged \`confirmed\` (with evidence), \`inferred\` (with reasoning), or \`unknown\`>
101145
-
101146
- ## Repository evidence
101147
- <concrete repository paths and symbols with what each shows; quote the relevant lines briefly>
101148
-
101149
- ## External sources
101150
- <URL, version or date checked, and the specific claim each source supports; write exactly \`None consulted.\` if no external source was needed, and say why>
101151
-
101152
- ## Grounded facts for the plan
101153
- <the facts the planner can rely on when decomposing and delegating, each tagged confirmed or inferred>
101154
-
101155
- ## Remaining ambiguity
101156
- <each open decision, who must decide it, and a recommended default; write exactly \`None observed.\` if none remain>
101157
-
101158
- ## Risks and constraints
101159
- <constraints from the repository or external platform, and risks the plan must account for>
101160
-
101161
- ## Work completed
101162
- <paths inspected, searches run, and sources opened, with the result of each>
101163
-
101164
- ## Handoff
101165
- Run the normal handoff command to \`${entryPoint}\` with this complete brief, then stop.
101166
-
101167
- \`\`\`bash
101168
- ${handoffCommand({
101169
- chatroomId: "<chatroom-id>",
101170
- role: "researcher",
101171
- nextRole: entryPoint,
101172
- cliEnvPrefix: ""
101173
- })}
101174
- \`\`\``;
101175
- }
101176
- var init_researcher_handoff_templates = __esm(() => {
101177
- init_command2();
101549
+ var init_planner_verifier_code = __esm(() => {
101550
+ init_verifier_handoff_templates();
101178
101551
  });
101179
101552
 
101180
- // ../../services/backend/prompts/teams/triage-handoff-templates.ts
101181
- function normalizeEntryPointRole5(entryPointRole) {
101182
- return entryPointRole.trim().toLowerCase() || "planner";
101183
- }
101184
- function getEntryPointToTriageHandoffTemplate(entryPointRole) {
101185
- const entryPoint = normalizeEntryPointRole5(entryPointRole);
101186
- return `${getHandoffRecipientVisibilityCallout("triage")}
101187
-
101188
- ## Handoff Template (${entryPoint} → triage)
101189
-
101190
- The automatically injected \`<user-message>\` is the authoritative request. Pass the reported bug, observed and expected behavior, reproduction details and commands, relevant constraints, and the files or symbols already suspected. Ask triage to investigate and report only. Triage may inspect code and attempt a focused automated regression test as evidence, but must not edit implementation files or implement a fix.
101191
-
101192
- After completing the investigation, triage must return the evidence-backed report to \`${entryPoint}\` with the normal handoff command.
101193
-
101194
- \`\`\`bash
101195
- ${handoffCommand({
101196
- chatroomId: "<chatroom-id>",
101197
- role: entryPoint,
101198
- nextRole: "triage",
101199
- cliEnvPrefix: ""
101200
- })}
101201
- \`\`\``;
101202
- }
101203
- function getTriageToEntryPointHandoffTemplate(entryPointRole) {
101204
- const entryPoint = normalizeEntryPointRole5(entryPointRole);
101205
- return `${getHandoffRecipientVisibilityCallout(entryPoint)}
101206
-
101207
- ## Handoff Template (Triage → ${entryPoint})
101208
-
101209
- Return a complete, evidence-backed investigation of the authoritative reported bug. Triage is advisory: do not edit implementation files or implement the proposed fix. Begin with the \`## Summary\` section, then use the remaining sections below in order. Use \`###\` for sub-items within a section. Cite concrete repository paths and symbols, observed behavior, commands, and test output. Distinguish confirmed findings from hypotheses; never claim a test proved behavior unless its failing assertion demonstrates the report.
101210
-
101211
- ## Summary
101212
- <briefly state the diagnosis and whether the root cause was confirmed or remains a hypothesis>
101213
-
101214
- ## Reported behavior
101215
- <state the reported symptoms and expected behavior, including reproduction details and constraints recovered from the request or relevant history>
101216
-
101217
- ## Root cause
101218
- <trace the relevant ownership, data, and control flow using concrete repository paths and symbols; explain the causal reasoning and explicitly label the finding as confirmed or a hypothesis>
101219
-
101220
- ## Reproduction attempt
101221
- <give the focused test path and exact command, the failing assertion or exact blocker, and the outcome; if reproduction was blocked, state what was tried and what additional information would help; do not fabricate proof>
101222
-
101223
- ## Proposed immediate fix
101224
- <recommend the smallest appropriate change, naming the likely files and the specific change; do not implement it>
101225
-
101226
- ## Systemic issues
101227
- <list each separate systemic concern with repository evidence, impact, and follow-up concern, or write exactly: None observed.>
101228
-
101229
- ## Work completed
101230
- <state the code paths inspected and every test or reproduction action taken, including results>
101231
-
101232
- ## Handoff
101233
- Run the normal handoff command to \`${entryPoint}\` with this complete report, then stop.
101234
-
101235
- \`\`\`bash
101236
- ${handoffCommand({
101237
- chatroomId: "<chatroom-id>",
101238
- role: "triage",
101239
- nextRole: entryPoint,
101240
- cliEnvPrefix: ""
101241
- })}
101242
- \`\`\``;
101243
- }
101244
- var init_triage_handoff_templates = __esm(() => {
101245
- init_command2();
101553
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-verifier-chat.ts
101554
+ var init_planner_verifier_chat = __esm(() => {
101555
+ init_planner_verifier_code();
101246
101556
  });
101247
101557
 
101248
101558
  // ../../services/backend/prompts/teams/duo/handoff-templates/planner.ts
101249
101559
  var duoPlannerHandoffContract;
101250
101560
  var init_planner = __esm(() => {
101251
- init_planner_to_builder();
101252
- init_planner_to_user();
101253
- init_chat_handoff_template();
101254
- init_architect_handoff_templates();
101255
- init_researcher_handoff_templates();
101256
- init_triage_handoff_templates();
101257
- init_uiux_engineer_handoff_templates();
101258
- init_verifier_handoff_templates();
101561
+ init_planner_architect_chat();
101562
+ init_planner_architect_code();
101563
+ init_planner_builder_chat();
101564
+ init_planner_builder_code();
101565
+ init_planner_researcher_chat();
101566
+ init_planner_researcher_code();
101567
+ init_planner_reviewer_chat();
101568
+ init_planner_reviewer_code();
101569
+ init_planner_triage_chat();
101570
+ init_planner_triage_code();
101571
+ init_planner_uiux_engineer_chat();
101572
+ init_planner_uiux_engineer_code();
101573
+ init_planner_user_chat();
101574
+ init_planner_user_code();
101575
+ init_planner_verifier_chat();
101576
+ init_planner_verifier_code();
101577
+ init_contracts();
101259
101578
  duoPlannerHandoffContract = {
101260
101579
  role: "planner",
101261
101580
  receivesFrom: [
@@ -101265,223 +101584,227 @@ var init_planner = __esm(() => {
101265
101584
  "uiux-engineer",
101266
101585
  "triage",
101267
101586
  "researcher",
101587
+ "reviewer",
101588
+ "verifier"
101589
+ ],
101590
+ returnsTo: [
101591
+ "user",
101592
+ "builder",
101593
+ "architect",
101594
+ "uiux-engineer",
101595
+ "triage",
101596
+ "researcher",
101597
+ "reviewer",
101268
101598
  "verifier"
101269
101599
  ],
101270
- returnsTo: ["builder", "architect", "uiux-engineer", "triage", "researcher", "verifier", "user"],
101271
101600
  outboundTemplates: {
101272
- builder: () => getPlannerToBuilderHandoffTemplate(),
101273
- architect: () => getEntryPointToArchitectHandoffTemplate("planner"),
101274
- "uiux-engineer": () => getEntryPointToUiuxEngineerHandoffTemplate("planner"),
101275
- triage: () => getEntryPointToTriageHandoffTemplate("planner"),
101276
- researcher: () => getEntryPointToResearcherHandoffTemplate("planner"),
101277
- verifier: () => getEntryPointToVerifierHandoffTemplate("planner"),
101278
- user: (query) => query.conversationMode === "chat" ? getChatToUserHandoffTemplate() : getPlannerToUserReportTemplate({
101279
- chatroomId: query.chatroomId,
101280
- role: query.role,
101281
- cliEnvPrefix: query.cliEnvPrefix
101601
+ builder: handoffTemplateByMode({
101602
+ chat: getPlannerBuilderCodeTemplate,
101603
+ code: getPlannerBuilderCodeTemplate
101604
+ }),
101605
+ architect: handoffTemplateByMode({
101606
+ chat: getPlannerArchitectCodeTemplate,
101607
+ code: getPlannerArchitectCodeTemplate
101608
+ }),
101609
+ "uiux-engineer": handoffTemplateByMode({
101610
+ chat: getPlannerUiuxEngineerCodeTemplate,
101611
+ code: getPlannerUiuxEngineerCodeTemplate
101612
+ }),
101613
+ triage: handoffTemplateByMode({
101614
+ chat: getPlannerTriageCodeTemplate,
101615
+ code: getPlannerTriageCodeTemplate
101616
+ }),
101617
+ researcher: handoffTemplateByMode({
101618
+ chat: getPlannerResearcherCodeTemplate,
101619
+ code: getPlannerResearcherCodeTemplate
101620
+ }),
101621
+ reviewer: handoffTemplateByMode({
101622
+ chat: getPlannerReviewerCodeTemplate,
101623
+ code: getPlannerReviewerCodeTemplate
101624
+ }),
101625
+ verifier: handoffTemplateByMode({
101626
+ chat: getPlannerVerifierCodeTemplate,
101627
+ code: getPlannerVerifierCodeTemplate
101628
+ }),
101629
+ user: handoffTemplateByMode({
101630
+ chat: getChatToUserHandoffTemplate,
101631
+ code: getPlannerUserCodeTemplate
101282
101632
  })
101283
101633
  }
101284
101634
  };
101285
101635
  });
101286
101636
 
101637
+ // ../../services/backend/prompts/teams/duo/handoff-templates/researcher-planner-code.ts
101638
+ function getResearcherPlannerCodeTemplate(query) {
101639
+ return getResearcherToEntryPointHandoffTemplate(query);
101640
+ }
101641
+ var init_researcher_planner_code = __esm(() => {
101642
+ init_researcher_handoff_templates();
101643
+ });
101644
+
101645
+ // ../../services/backend/prompts/teams/duo/handoff-templates/researcher-planner-chat.ts
101646
+ var init_researcher_planner_chat = __esm(() => {
101647
+ init_researcher_planner_code();
101648
+ });
101649
+
101287
101650
  // ../../services/backend/prompts/teams/duo/handoff-templates/researcher.ts
101288
101651
  var duoResearcherHandoffContract;
101289
101652
  var init_researcher = __esm(() => {
101290
- init_researcher_handoff_templates();
101653
+ init_researcher_planner_chat();
101654
+ init_researcher_planner_code();
101655
+ init_contracts();
101291
101656
  duoResearcherHandoffContract = {
101292
101657
  role: "researcher",
101293
101658
  receivesFrom: ["planner"],
101294
101659
  returnsTo: ["planner"],
101295
101660
  outboundTemplates: {
101296
- planner: () => getResearcherToEntryPointHandoffTemplate("planner")
101661
+ planner: handoffTemplateByMode({
101662
+ chat: getResearcherPlannerCodeTemplate,
101663
+ code: getResearcherPlannerCodeTemplate
101664
+ })
101297
101665
  }
101298
101666
  };
101299
101667
  });
101300
101668
 
101669
+ // ../../services/backend/prompts/teams/duo/handoff-templates/reviewer-planner-code.ts
101670
+ function getReviewerPlannerCodeTemplate(query) {
101671
+ return getReviewerToEntryPointHandoffTemplate(query);
101672
+ }
101673
+ var init_reviewer_planner_code = __esm(() => {
101674
+ init_reviewer_handoff_templates();
101675
+ });
101676
+
101677
+ // ../../services/backend/prompts/teams/duo/handoff-templates/reviewer-planner-chat.ts
101678
+ var init_reviewer_planner_chat = __esm(() => {
101679
+ init_reviewer_planner_code();
101680
+ });
101681
+
101682
+ // ../../services/backend/prompts/teams/duo/handoff-templates/reviewer.ts
101683
+ var duoReviewerHandoffContract;
101684
+ var init_reviewer = __esm(() => {
101685
+ init_reviewer_planner_chat();
101686
+ init_reviewer_planner_code();
101687
+ init_contracts();
101688
+ duoReviewerHandoffContract = {
101689
+ role: "reviewer",
101690
+ receivesFrom: ["planner"],
101691
+ returnsTo: ["planner"],
101692
+ outboundTemplates: {
101693
+ planner: handoffTemplateByMode({
101694
+ chat: getReviewerPlannerCodeTemplate,
101695
+ code: getReviewerPlannerCodeTemplate
101696
+ })
101697
+ }
101698
+ };
101699
+ });
101700
+
101701
+ // ../../services/backend/prompts/teams/duo/handoff-templates/triage-planner-code.ts
101702
+ function getTriagePlannerCodeTemplate(query) {
101703
+ return getTriageToEntryPointHandoffTemplate(query);
101704
+ }
101705
+ var init_triage_planner_code = __esm(() => {
101706
+ init_triage_handoff_templates();
101707
+ });
101708
+
101709
+ // ../../services/backend/prompts/teams/duo/handoff-templates/triage-planner-chat.ts
101710
+ var init_triage_planner_chat = __esm(() => {
101711
+ init_triage_planner_code();
101712
+ });
101713
+
101301
101714
  // ../../services/backend/prompts/teams/duo/handoff-templates/triage.ts
101302
101715
  var duoTriageHandoffContract;
101303
101716
  var init_triage = __esm(() => {
101304
- init_triage_handoff_templates();
101717
+ init_triage_planner_chat();
101718
+ init_triage_planner_code();
101719
+ init_contracts();
101305
101720
  duoTriageHandoffContract = {
101306
101721
  role: "triage",
101307
101722
  receivesFrom: ["planner"],
101308
101723
  returnsTo: ["planner"],
101309
101724
  outboundTemplates: {
101310
- planner: () => getTriageToEntryPointHandoffTemplate("planner")
101725
+ planner: handoffTemplateByMode({
101726
+ chat: getTriagePlannerCodeTemplate,
101727
+ code: getTriagePlannerCodeTemplate
101728
+ })
101311
101729
  }
101312
101730
  };
101313
101731
  });
101314
101732
 
101733
+ // ../../services/backend/prompts/teams/duo/handoff-templates/uiux-engineer-planner-code.ts
101734
+ function getUiuxEngineerPlannerCodeTemplate(query) {
101735
+ return getUiuxEngineerToEntryPointHandoffTemplate(query);
101736
+ }
101737
+ var init_uiux_engineer_planner_code = __esm(() => {
101738
+ init_uiux_engineer_handoff_templates();
101739
+ });
101740
+
101741
+ // ../../services/backend/prompts/teams/duo/handoff-templates/uiux-engineer-planner-chat.ts
101742
+ var init_uiux_engineer_planner_chat = __esm(() => {
101743
+ init_uiux_engineer_planner_code();
101744
+ });
101745
+
101315
101746
  // ../../services/backend/prompts/teams/duo/handoff-templates/uiux-engineer.ts
101316
101747
  var duoUiuxEngineerHandoffContract;
101317
101748
  var init_uiux_engineer = __esm(() => {
101318
- init_uiux_engineer_handoff_templates();
101749
+ init_uiux_engineer_planner_chat();
101750
+ init_uiux_engineer_planner_code();
101751
+ init_contracts();
101319
101752
  duoUiuxEngineerHandoffContract = {
101320
101753
  role: "uiux-engineer",
101321
101754
  receivesFrom: ["planner"],
101322
101755
  returnsTo: ["planner"],
101323
101756
  outboundTemplates: {
101324
- planner: () => getUiuxEngineerToEntryPointHandoffTemplate("planner")
101757
+ planner: handoffTemplateByMode({
101758
+ chat: getUiuxEngineerPlannerCodeTemplate,
101759
+ code: getUiuxEngineerPlannerCodeTemplate
101760
+ })
101325
101761
  }
101326
101762
  };
101327
101763
  });
101328
101764
 
101765
+ // ../../services/backend/prompts/teams/duo/handoff-templates/verifier-planner-code.ts
101766
+ function getVerifierPlannerCodeTemplate(query) {
101767
+ return getVerifierToEntryPointHandoffTemplate(query);
101768
+ }
101769
+ var init_verifier_planner_code = __esm(() => {
101770
+ init_verifier_handoff_templates();
101771
+ });
101772
+
101773
+ // ../../services/backend/prompts/teams/duo/handoff-templates/verifier-planner-chat.ts
101774
+ var init_verifier_planner_chat = __esm(() => {
101775
+ init_verifier_planner_code();
101776
+ });
101777
+
101329
101778
  // ../../services/backend/prompts/teams/duo/handoff-templates/verifier.ts
101330
101779
  var duoVerifierHandoffContract;
101331
101780
  var init_verifier = __esm(() => {
101332
- init_verifier_handoff_templates();
101781
+ init_verifier_planner_chat();
101782
+ init_verifier_planner_code();
101783
+ init_contracts();
101333
101784
  duoVerifierHandoffContract = {
101334
101785
  role: "verifier",
101335
101786
  receivesFrom: ["planner"],
101336
101787
  returnsTo: ["planner"],
101337
101788
  outboundTemplates: {
101338
- planner: () => getVerifierToEntryPointHandoffTemplate("planner")
101789
+ planner: handoffTemplateByMode({
101790
+ chat: getVerifierPlannerCodeTemplate,
101791
+ code: getVerifierPlannerCodeTemplate
101792
+ })
101339
101793
  }
101340
101794
  };
101341
101795
  });
101342
101796
 
101343
- // ../shared/src/domain/chatroom-role.ts
101344
- var CHATROOM_ROLE_USER = "user";
101345
- var init_chatroom_role = __esm(() => {
101346
- init_agent_role();
101347
- });
101348
-
101349
- // ../../services/backend/prompts/cli/handoff-templates/contracts.ts
101350
- function validateRoleHandoffContracts(contracts) {
101351
- const byRole = new Map;
101352
- for (const contract of contracts) {
101353
- const key = contract.role.toLowerCase();
101354
- if (byRole.has(key)) {
101355
- throw new Error(`Duplicate role handoff contract: "${contract.role}"`);
101356
- }
101357
- byRole.set(key, contract);
101358
- }
101359
- for (const contract of contracts) {
101360
- const ownerKey = contract.role.toLowerCase();
101361
- for (const target of Object.keys(contract.outboundTemplates)) {
101362
- const targetKey = target.toLowerCase();
101363
- if (targetKey === "user")
101364
- continue;
101365
- const targetContract = byRole.get(targetKey);
101366
- if (!targetContract) {
101367
- throw new Error(`Role "${contract.role}" declares an outbound template to "${target}", which is neither 'user' nor a role listed in the catalogue`);
101368
- }
101369
- const declaresOwner = (targetContract.receivesFrom ?? []).some((from) => from.toLowerCase() === ownerKey);
101370
- if (!declaresOwner) {
101371
- throw new Error(`Reciprocity failure: role "${targetContract.role}" receives from "${contract.role}" (via the ${contract.role} → ${target} template) but does not declare "${contract.role}" in receivesFrom`);
101372
- }
101373
- }
101374
- }
101375
- }
101376
- function validateBuiltinOwners(teamName, expectedRoles, contracts) {
101377
- const actualRoles = new Set;
101378
- const byRole = new Map;
101379
- for (const contract of contracts) {
101380
- const normalizedOwner = contract.role.trim().toLowerCase();
101381
- if (!normalizedOwner || contract.role !== normalizedOwner) {
101382
- throw new Error(`${teamName} handoff owner "${contract.role}" is not canonical`);
101383
- }
101384
- if (actualRoles.has(normalizedOwner)) {
101385
- throw new Error(`${teamName} has duplicate handoff contract owner "${contract.role}"`);
101386
- }
101387
- if (!expectedRoles.has(normalizedOwner)) {
101388
- throw new Error(`${teamName} has unexpected handoff contract role "${contract.role}"`);
101389
- }
101390
- actualRoles.add(normalizedOwner);
101391
- byRole.set(normalizedOwner, contract);
101392
- }
101393
- for (const role of expectedRoles) {
101394
- if (!actualRoles.has(role)) {
101395
- throw new Error(`${teamName} is missing handoff contract for role "${role}"`);
101396
- }
101397
- }
101398
- return byRole;
101399
- }
101400
- function validateReferenceTargets(teamName, owner, label, targets, allowedTargets) {
101401
- const seen = new Set;
101402
- for (const target of targets) {
101403
- const normalizedTarget = target.trim().toLowerCase();
101404
- if (target !== normalizedTarget || !allowedTargets.has(normalizedTarget)) {
101405
- throw new Error(`${teamName} role "${owner}" has invalid ${label} target "${target}"`);
101406
- }
101407
- if (seen.has(normalizedTarget)) {
101408
- throw new Error(`${teamName} role "${owner}" has duplicate ${label} target "${target}"`);
101409
- }
101410
- seen.add(normalizedTarget);
101411
- }
101412
- }
101413
- function validateBuiltinReferences(teamName, allowedTargets, contracts) {
101414
- for (const contract of contracts) {
101415
- const owner = contract.role;
101416
- validateReferenceTargets(teamName, owner, "receivesFrom", contract.receivesFrom, allowedTargets);
101417
- validateReferenceTargets(teamName, owner, "returnsTo", contract.returnsTo, allowedTargets);
101418
- const outboundTargets = Object.keys(contract.outboundTemplates);
101419
- if (outboundTargets.length === 0) {
101420
- throw new Error(`${teamName} role "${owner}" must have an outbound handoff capability`);
101421
- }
101422
- const returnsTo = new Set(contract.returnsTo);
101423
- const outbound = new Set(outboundTargets);
101424
- validateReferenceTargets(teamName, owner, "outbound", outboundTargets, allowedTargets);
101425
- for (const target of outboundTargets) {
101426
- if (typeof contract.outboundTemplates[target] !== "function") {
101427
- throw new Error(`${teamName} role "${owner}" has no outbound getter for target "${target}"`);
101428
- }
101429
- }
101430
- if (returnsTo.size !== outbound.size || [...returnsTo].some((target) => !outbound.has(target))) {
101431
- throw new Error(`${teamName} role "${owner}" returnsTo targets must exactly match outbound targets`);
101432
- }
101433
- }
101434
- }
101435
- function validateBuiltinReciprocity(teamName, byRole, contracts) {
101436
- for (const contract of contracts) {
101437
- const owner = contract.role;
101438
- for (const receivedFrom of contract.receivesFrom) {
101439
- if (receivedFrom === CHATROOM_ROLE_USER)
101440
- continue;
101441
- const source = byRole.get(receivedFrom);
101442
- if (!source?.outboundTemplates[owner]) {
101443
- throw new Error(`${teamName} role "${owner}" receives from "${receivedFrom}" without a reverse outbound edge`);
101444
- }
101445
- }
101446
- }
101447
- try {
101448
- validateRoleHandoffContracts(contracts);
101449
- } catch (error51) {
101450
- const contextualError = new Error(`${teamName}: ${error51 instanceof Error ? error51.message : String(error51)}`);
101451
- Object.defineProperty(contextualError, "cause", { value: error51, configurable: true });
101452
- throw contextualError;
101453
- }
101454
- }
101455
- function validateBuiltinTeamRoleHandoffContracts(teamId, contracts) {
101456
- const teamName = TEAM_PRESETS[teamId].name;
101457
- const expectedRoles = new Set(TEAM_PRESETS[teamId].roles);
101458
- const byRole = validateBuiltinOwners(teamName, expectedRoles, contracts);
101459
- const allowedTargets = new Set([...expectedRoles, CHATROOM_ROLE_USER]);
101460
- validateBuiltinReferences(teamName, allowedTargets, contracts);
101461
- validateBuiltinReciprocity(teamName, byRole, contracts);
101462
- }
101463
- var init_contracts = __esm(() => {
101464
- init_chatroom_role();
101465
- init_team_presets();
101466
- });
101467
-
101468
101797
  // ../../services/backend/prompts/teams/duo/handoff-templates/index.ts
101469
101798
  function listDuoRoleHandoffContracts() {
101470
101799
  return validatedDuoRoleHandoffContracts;
101471
101800
  }
101472
- function getDuoHandoffTemplate(query) {
101473
- const fromRole = query.fromRole.toLowerCase();
101474
- const toRole = query.toRole.toLowerCase();
101475
- const contract = validatedDuoRoleHandoffContracts.find((candidate) => candidate.role.toLowerCase() === fromRole);
101476
- const getter = contract?.outboundTemplates[toRole];
101477
- return getter?.(query) ?? null;
101478
- }
101479
101801
  var DUO_ROLE_HANDOFF_CATALOG, DUO_ROLE_HANDOFF_CONTRACTS, validatedDuoRoleHandoffContracts;
101480
101802
  var init_handoff_templates = __esm(() => {
101481
101803
  init_architect();
101482
101804
  init_builder();
101483
101805
  init_planner();
101484
101806
  init_researcher();
101807
+ init_reviewer();
101485
101808
  init_triage();
101486
101809
  init_uiux_engineer();
101487
101810
  init_verifier();
@@ -101491,6 +101814,7 @@ var init_handoff_templates = __esm(() => {
101491
101814
  builder: duoBuilderHandoffContract,
101492
101815
  architect: duoArchitectHandoffContract,
101493
101816
  researcher: duoResearcherHandoffContract,
101817
+ reviewer: duoReviewerHandoffContract,
101494
101818
  "uiux-engineer": duoUiuxEngineerHandoffContract,
101495
101819
  triage: duoTriageHandoffContract,
101496
101820
  verifier: duoVerifierHandoffContract
@@ -101502,99 +101826,240 @@ var init_handoff_templates = __esm(() => {
101502
101826
  })();
101503
101827
  });
101504
101828
 
101829
+ // ../../services/backend/prompts/teams/solo/handoff-templates/architect-solo-code.ts
101830
+ function getArchitectSoloCodeTemplate(query) {
101831
+ return getArchitectToEntryPointHandoffTemplate(query);
101832
+ }
101833
+ var init_architect_solo_code = __esm(() => {
101834
+ init_architect_handoff_templates();
101835
+ });
101836
+
101837
+ // ../../services/backend/prompts/teams/solo/handoff-templates/architect-solo-chat.ts
101838
+ var init_architect_solo_chat = __esm(() => {
101839
+ init_architect_solo_code();
101840
+ });
101841
+
101505
101842
  // ../../services/backend/prompts/teams/solo/handoff-templates/architect.ts
101506
101843
  var soloArchitectHandoffContract;
101507
101844
  var init_architect2 = __esm(() => {
101508
- init_architect_handoff_templates();
101845
+ init_architect_solo_chat();
101846
+ init_architect_solo_code();
101847
+ init_contracts();
101509
101848
  soloArchitectHandoffContract = {
101510
101849
  role: "architect",
101511
101850
  receivesFrom: ["solo"],
101512
101851
  returnsTo: ["solo"],
101513
101852
  outboundTemplates: {
101514
- solo: () => getArchitectToEntryPointHandoffTemplate("solo")
101853
+ solo: handoffTemplateByMode({
101854
+ chat: getArchitectSoloCodeTemplate,
101855
+ code: getArchitectSoloCodeTemplate
101856
+ })
101515
101857
  }
101516
101858
  };
101517
101859
  });
101518
101860
 
101519
- // ../../services/backend/prompts/teams/solo/handoff-templates/solo-to-user.ts
101520
- function getSoloToUserReportTemplate(roleGuidanceContext) {
101521
- return `${getHandoffRecipientVisibilityCallout("user")}
101861
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-architect-code.ts
101862
+ function getSoloArchitectCodeTemplate(query) {
101863
+ return getEntryPointToArchitectHandoffTemplate(query);
101864
+ }
101865
+ var init_solo_architect_code = __esm(() => {
101866
+ init_architect_handoff_templates();
101867
+ });
101868
+
101869
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-architect-chat.ts
101870
+ var init_solo_architect_chat = __esm(() => {
101871
+ init_solo_architect_code();
101872
+ });
101522
101873
 
101523
- ${getHandoffReportTemplateIntro("Report Template (Solo → User)")}
101874
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-triage-code.ts
101875
+ function getSoloTriageCodeTemplate(query) {
101876
+ return getEntryPointToTriageHandoffTemplate(query);
101877
+ }
101878
+ var init_solo_triage_code = __esm(() => {
101879
+ init_triage_handoff_templates();
101880
+ });
101881
+
101882
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-triage-chat.ts
101883
+ var init_solo_triage_chat = __esm(() => {
101884
+ init_solo_triage_code();
101885
+ });
101886
+
101887
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-uiux-engineer-code.ts
101888
+ function getSoloUiuxEngineerCodeTemplate(query) {
101889
+ return getEntryPointToUiuxEngineerHandoffTemplate(query);
101890
+ }
101891
+ var init_solo_uiux_engineer_code = __esm(() => {
101892
+ init_uiux_engineer_handoff_templates();
101893
+ });
101894
+
101895
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-uiux-engineer-chat.ts
101896
+ var init_solo_uiux_engineer_chat = __esm(() => {
101897
+ init_solo_uiux_engineer_code();
101898
+ });
101899
+
101900
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-user-chat.ts
101901
+ var init_solo_user_chat = () => {};
101902
+
101903
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-user-code.ts
101904
+ function getSoloUserCodeTemplate(roleGuidanceContext) {
101905
+ return `${getHandoffReportTemplateIntro()}
101524
101906
 
101525
101907
  \`\`\`markdown
101526
101908
  ${getHandoffReportTemplateBody(roleGuidanceContext, { includeProofOfVerification: true })}
101527
101909
  \`\`\``;
101528
101910
  }
101529
- var init_solo_to_user = __esm(() => {
101911
+ var init_solo_user_code = __esm(() => {
101530
101912
  init_handoff_report_template_body();
101531
101913
  });
101532
101914
 
101915
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-verifier-code.ts
101916
+ function getSoloVerifierCodeTemplate(query) {
101917
+ return getEntryPointToVerifierHandoffTemplate(query);
101918
+ }
101919
+ var init_solo_verifier_code = __esm(() => {
101920
+ init_verifier_handoff_templates();
101921
+ });
101922
+
101923
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-verifier-chat.ts
101924
+ var init_solo_verifier_chat = __esm(() => {
101925
+ init_solo_verifier_code();
101926
+ });
101927
+
101533
101928
  // ../../services/backend/prompts/teams/solo/handoff-templates/solo.ts
101534
101929
  var soloHandoffContract;
101535
101930
  var init_solo = __esm(() => {
101536
- init_solo_to_user();
101537
- init_chat_handoff_template();
101538
- init_architect_handoff_templates();
101539
- init_triage_handoff_templates();
101540
- init_uiux_engineer_handoff_templates();
101541
- init_verifier_handoff_templates();
101931
+ init_solo_architect_chat();
101932
+ init_solo_architect_code();
101933
+ init_solo_triage_chat();
101934
+ init_solo_triage_code();
101935
+ init_solo_uiux_engineer_chat();
101936
+ init_solo_uiux_engineer_code();
101937
+ init_solo_user_chat();
101938
+ init_solo_user_code();
101939
+ init_solo_verifier_chat();
101940
+ init_solo_verifier_code();
101941
+ init_contracts();
101542
101942
  soloHandoffContract = {
101543
101943
  role: "solo",
101544
101944
  receivesFrom: ["user", "architect", "uiux-engineer", "triage", "verifier"],
101545
- returnsTo: ["architect", "uiux-engineer", "triage", "verifier", "user"],
101945
+ returnsTo: ["user", "architect", "uiux-engineer", "triage", "verifier"],
101546
101946
  outboundTemplates: {
101547
- architect: () => getEntryPointToArchitectHandoffTemplate("solo"),
101548
- "uiux-engineer": () => getEntryPointToUiuxEngineerHandoffTemplate("solo"),
101549
- triage: () => getEntryPointToTriageHandoffTemplate("solo"),
101550
- verifier: () => getEntryPointToVerifierHandoffTemplate("solo"),
101551
- user: (query) => query.conversationMode === "chat" ? getChatToUserHandoffTemplate() : getSoloToUserReportTemplate({
101552
- chatroomId: query.chatroomId,
101553
- role: query.role,
101554
- cliEnvPrefix: query.cliEnvPrefix
101947
+ architect: handoffTemplateByMode({
101948
+ chat: getSoloArchitectCodeTemplate,
101949
+ code: getSoloArchitectCodeTemplate
101950
+ }),
101951
+ "uiux-engineer": handoffTemplateByMode({
101952
+ chat: getSoloUiuxEngineerCodeTemplate,
101953
+ code: getSoloUiuxEngineerCodeTemplate
101954
+ }),
101955
+ triage: handoffTemplateByMode({
101956
+ chat: getSoloTriageCodeTemplate,
101957
+ code: getSoloTriageCodeTemplate
101958
+ }),
101959
+ verifier: handoffTemplateByMode({
101960
+ chat: getSoloVerifierCodeTemplate,
101961
+ code: getSoloVerifierCodeTemplate
101962
+ }),
101963
+ user: handoffTemplateByMode({
101964
+ chat: getChatToUserHandoffTemplate,
101965
+ code: getSoloUserCodeTemplate
101555
101966
  })
101556
101967
  }
101557
101968
  };
101558
101969
  });
101559
101970
 
101971
+ // ../../services/backend/prompts/teams/solo/handoff-templates/triage-solo-code.ts
101972
+ function getTriageSoloCodeTemplate(query) {
101973
+ return getTriageToEntryPointHandoffTemplate(query);
101974
+ }
101975
+ var init_triage_solo_code = __esm(() => {
101976
+ init_triage_handoff_templates();
101977
+ });
101978
+
101979
+ // ../../services/backend/prompts/teams/solo/handoff-templates/triage-solo-chat.ts
101980
+ var init_triage_solo_chat = __esm(() => {
101981
+ init_triage_solo_code();
101982
+ });
101983
+
101560
101984
  // ../../services/backend/prompts/teams/solo/handoff-templates/triage.ts
101561
101985
  var soloTriageHandoffContract;
101562
101986
  var init_triage2 = __esm(() => {
101563
- init_triage_handoff_templates();
101987
+ init_triage_solo_chat();
101988
+ init_triage_solo_code();
101989
+ init_contracts();
101564
101990
  soloTriageHandoffContract = {
101565
101991
  role: "triage",
101566
101992
  receivesFrom: ["solo"],
101567
101993
  returnsTo: ["solo"],
101568
101994
  outboundTemplates: {
101569
- solo: () => getTriageToEntryPointHandoffTemplate("solo")
101995
+ solo: handoffTemplateByMode({
101996
+ chat: getTriageSoloCodeTemplate,
101997
+ code: getTriageSoloCodeTemplate
101998
+ })
101570
101999
  }
101571
102000
  };
101572
102001
  });
101573
102002
 
102003
+ // ../../services/backend/prompts/teams/solo/handoff-templates/uiux-engineer-solo-code.ts
102004
+ function getUiuxEngineerSoloCodeTemplate(query) {
102005
+ return getUiuxEngineerToEntryPointHandoffTemplate(query);
102006
+ }
102007
+ var init_uiux_engineer_solo_code = __esm(() => {
102008
+ init_uiux_engineer_handoff_templates();
102009
+ });
102010
+
102011
+ // ../../services/backend/prompts/teams/solo/handoff-templates/uiux-engineer-solo-chat.ts
102012
+ var init_uiux_engineer_solo_chat = __esm(() => {
102013
+ init_uiux_engineer_solo_code();
102014
+ });
102015
+
101574
102016
  // ../../services/backend/prompts/teams/solo/handoff-templates/uiux-engineer.ts
101575
102017
  var soloUiuxEngineerHandoffContract;
101576
102018
  var init_uiux_engineer2 = __esm(() => {
101577
- init_uiux_engineer_handoff_templates();
102019
+ init_uiux_engineer_solo_chat();
102020
+ init_uiux_engineer_solo_code();
102021
+ init_contracts();
101578
102022
  soloUiuxEngineerHandoffContract = {
101579
102023
  role: "uiux-engineer",
101580
102024
  receivesFrom: ["solo"],
101581
102025
  returnsTo: ["solo"],
101582
102026
  outboundTemplates: {
101583
- solo: () => getUiuxEngineerToEntryPointHandoffTemplate("solo")
102027
+ solo: handoffTemplateByMode({
102028
+ chat: getUiuxEngineerSoloCodeTemplate,
102029
+ code: getUiuxEngineerSoloCodeTemplate
102030
+ })
101584
102031
  }
101585
102032
  };
101586
102033
  });
101587
102034
 
102035
+ // ../../services/backend/prompts/teams/solo/handoff-templates/verifier-solo-code.ts
102036
+ function getVerifierSoloCodeTemplate(query) {
102037
+ return getVerifierToEntryPointHandoffTemplate(query);
102038
+ }
102039
+ var init_verifier_solo_code = __esm(() => {
102040
+ init_verifier_handoff_templates();
102041
+ });
102042
+
102043
+ // ../../services/backend/prompts/teams/solo/handoff-templates/verifier-solo-chat.ts
102044
+ var init_verifier_solo_chat = __esm(() => {
102045
+ init_verifier_solo_code();
102046
+ });
102047
+
101588
102048
  // ../../services/backend/prompts/teams/solo/handoff-templates/verifier.ts
101589
102049
  var soloVerifierHandoffContract;
101590
102050
  var init_verifier2 = __esm(() => {
101591
- init_verifier_handoff_templates();
102051
+ init_verifier_solo_chat();
102052
+ init_verifier_solo_code();
102053
+ init_contracts();
101592
102054
  soloVerifierHandoffContract = {
101593
102055
  role: "verifier",
101594
102056
  receivesFrom: ["solo"],
101595
102057
  returnsTo: ["solo"],
101596
102058
  outboundTemplates: {
101597
- solo: () => getVerifierToEntryPointHandoffTemplate("solo")
102059
+ solo: handoffTemplateByMode({
102060
+ chat: getVerifierSoloCodeTemplate,
102061
+ code: getVerifierSoloCodeTemplate
102062
+ })
101598
102063
  }
101599
102064
  };
101600
102065
  });
@@ -101603,13 +102068,6 @@ var init_verifier2 = __esm(() => {
101603
102068
  function listSoloRoleHandoffContracts() {
101604
102069
  return validatedSoloRoleHandoffContracts;
101605
102070
  }
101606
- function getSoloHandoffTemplate(query) {
101607
- const fromRole = query.fromRole.toLowerCase();
101608
- const toRole = query.toRole.toLowerCase();
101609
- const contract = validatedSoloRoleHandoffContracts.find((candidate) => candidate.role.toLowerCase() === fromRole);
101610
- const getter = contract?.outboundTemplates[toRole];
101611
- return getter?.(query) ?? null;
101612
- }
101613
102071
  var SOLO_ROLE_HANDOFF_CATALOG, SOLO_ROLE_HANDOFF_CONTRACTS, validatedSoloRoleHandoffContracts;
101614
102072
  var init_handoff_templates2 = __esm(() => {
101615
102073
  init_architect2();
@@ -101633,85 +102091,117 @@ var init_handoff_templates2 = __esm(() => {
101633
102091
  });
101634
102092
 
101635
102093
  // ../../services/backend/prompts/cli/handoff-templates/index.ts
101636
- function resolveTeamContracts(teamId) {
101637
- const team = (teamId ?? "duo").toLowerCase();
101638
- if (team === "duo")
101639
- return listDuoRoleHandoffContracts();
101640
- if (team === "solo")
101641
- return listSoloRoleHandoffContracts();
101642
- return null;
102094
+ function listHandoffTemplatePairs(teamId, fromRole) {
102095
+ const team = (teamId ?? DEFAULT_HANDOFF_TEAM_ID).trim().toLowerCase();
102096
+ if (!isTeamPresetId(team))
102097
+ return [];
102098
+ const normalizedFrom = fromRole === undefined ? undefined : fromRole.trim().toLowerCase();
102099
+ const contracts = normalizedFrom === undefined ? BUILTIN_TEAM_HANDOFF_CONTRACTS[team] : BUILTIN_TEAM_HANDOFF_CONTRACTS[team].filter((contract) => contract.role.toLowerCase() === normalizedFrom);
102100
+ return contracts.flatMap((contract) => contract.returnsTo.map((toRole) => ({
102101
+ teamId: team,
102102
+ fromRole: contract.role,
102103
+ toRole
102104
+ })));
102105
+ }
102106
+ function resolveHandoffTemplatePair(input, command) {
102107
+ const from = normalizeHandoffRole(input.from);
102108
+ const to = normalizeHandoffRole(input.to);
102109
+ const legacyRole = normalizeHandoffRole(input.legacyRole);
102110
+ const legacyNextRole = normalizeHandoffRole(input.legacyNextRole);
102111
+ const team = (input.teamId ?? DEFAULT_HANDOFF_TEAM_ID).trim().toLowerCase();
102112
+ if (from !== undefined && to !== undefined) {
102113
+ if (!isTeamPresetId(team)) {
102114
+ throw new HandoffTemplatePairError("UNKNOWN_TEAM", unknownTeamMessage(team));
102115
+ }
102116
+ const contracts = BUILTIN_TEAM_HANDOFF_CONTRACTS[team];
102117
+ const contract = contracts.find((candidate) => candidate.role.toLowerCase() === from);
102118
+ if (!contract) {
102119
+ throw new HandoffTemplatePairError("UNKNOWN_FROM_ROLE", unknownFromRoleMessage({ from, team, roles: contracts.map((c) => c.role) }));
102120
+ }
102121
+ if (!contract.returnsTo.includes(to)) {
102122
+ throw new HandoffTemplatePairError("UNKNOWN_PAIR", unknownPairMessage({ from, to, team, recipients: contract.returnsTo }));
102123
+ }
102124
+ return { teamId: team, fromRole: contract.role, toRole: to };
102125
+ }
102126
+ if (legacyRole !== undefined || legacyNextRole !== undefined) {
102127
+ throw new HandoffTemplatePairError("LEGACY_ROLE_FLAGS", legacyRoleFlagsMessage(command, {
102128
+ teamId: team,
102129
+ legacyRole,
102130
+ legacyNextRole,
102131
+ mode: normalizeHandoffMode(input.mode),
102132
+ rolePairs: legacyRole === undefined ? undefined : listHandoffTemplatePairs(team, legacyRole)
102133
+ }));
102134
+ }
102135
+ const missing = from === undefined && to === undefined ? "--from, --to" : from === undefined ? "--from" : "--to";
102136
+ throw new HandoffTemplatePairError("MISSING_PAIR", missingPairMessage(command, missing));
102137
+ }
102138
+ function resolveHandoffTemplateSelection(input, command) {
102139
+ const pair = resolveHandoffTemplatePair(input, command);
102140
+ const mode = normalizeHandoffMode(input.mode);
102141
+ if (mode === undefined) {
102142
+ throw new HandoffTemplatePairError("MISSING_MODE", missingModeMessage(command));
102143
+ }
102144
+ if (!isConversationMode2(mode)) {
102145
+ throw new HandoffTemplatePairError("UNKNOWN_MODE", unknownModeMessage(mode));
102146
+ }
102147
+ return { pair, mode };
101643
102148
  }
101644
- function listHandoffTemplates(query) {
101645
- const teamId = (query.teamId ?? "duo").toLowerCase();
101646
- const contracts = resolveTeamContracts(teamId);
101647
- if (!contracts)
102149
+ function renderHandoffTemplate(pair, options) {
102150
+ const contract = BUILTIN_TEAM_HANDOFF_CONTRACTS[pair.teamId].find((candidate) => candidate.role.toLowerCase() === pair.fromRole);
102151
+ const getter = contract?.outboundTemplates[pair.toRole];
102152
+ if (!getter)
101648
102153
  return null;
101649
- const contract = contracts.find((candidate) => candidate.role.toLowerCase() === query.role.toLowerCase());
101650
- if (!contract)
102154
+ const body = getter({
102155
+ ...options,
102156
+ teamId: pair.teamId,
102157
+ fromRole: pair.fromRole,
102158
+ toRole: pair.toRole,
102159
+ role: pair.fromRole
102160
+ });
102161
+ if (!body)
101651
102162
  return null;
101652
- const templates = [];
101653
- for (const toRole of Object.keys(contract.outboundTemplates).sort()) {
101654
- const getter = contract.outboundTemplates[toRole];
101655
- const template = getter?.({
101656
- fromRole: contract.role,
101657
- toRole,
101658
- teamId,
101659
- nativeIntegration: query.nativeIntegration,
101660
- chatroomId: query.chatroomId,
101661
- role: contract.role,
101662
- cliEnvPrefix: query.cliEnvPrefix,
101663
- conversationMode: query.conversationMode
101664
- });
101665
- if (!template)
101666
- continue;
101667
- templates.push({ fromRole: contract.role, toRole, template });
101668
- }
101669
- return {
101670
- teamId,
101671
- role: contract.role,
101672
- receivesFrom: [...contract.receivesFrom],
101673
- returnsTo: [...contract.returnsTo],
101674
- templates
101675
- };
101676
- }
101677
- function getHandoffTemplate(query) {
101678
- const team = (query.teamId ?? "duo").toLowerCase();
101679
- if (team === "duo")
101680
- return getDuoHandoffTemplate(query);
101681
- if (team === "solo")
101682
- return getSoloHandoffTemplate(query);
101683
- return null;
102163
+ return [
102164
+ getHandoffRecipientVisibilityCallout(pair.toRole),
102165
+ getHandoffTemplateTitleLine(pair),
102166
+ body
102167
+ ].join(`
102168
+
102169
+ `);
102170
+ }
102171
+ function getReplyHandoffTemplatePair(pair) {
102172
+ const contract = BUILTIN_TEAM_HANDOFF_CONTRACTS[pair.teamId].find((candidate) => candidate.role.toLowerCase() === pair.toRole);
102173
+ const getter = contract?.outboundTemplates[pair.fromRole];
102174
+ if (!getter)
102175
+ return null;
102176
+ return { teamId: pair.teamId, fromRole: pair.toRole, toRole: pair.fromRole };
101684
102177
  }
102178
+ var BUILTIN_TEAM_HANDOFF_CONTRACTS;
101685
102179
  var init_handoff_templates3 = __esm(() => {
102180
+ init_pair();
101686
102181
  init_handoff_templates();
101687
102182
  init_handoff_templates2();
102183
+ BUILTIN_TEAM_HANDOFF_CONTRACTS = {
102184
+ duo: listDuoRoleHandoffContracts(),
102185
+ solo: listSoloRoleHandoffContracts()
102186
+ };
101688
102187
  });
101689
102188
 
101690
102189
  // ../../services/backend/prompts/cli/handoff/view-template.ts
101691
102190
  function viewHandoffTemplate(params) {
101692
- if (params.nextRole === undefined) {
101693
- const role = params.role.trim().toLowerCase();
101694
- if (role === "architect")
101695
- return getGenericArchitectToEntryPointHandoffTemplate();
101696
- if (role === "uiux-engineer")
101697
- return getGenericUiuxEngineerToEntryPointHandoffTemplate();
101698
- throw new Error(`Role-only handoff template viewing is supported only for architect or uiux-engineer, not ${params.role}`);
101699
- }
101700
- const template = getHandoffTemplate({
101701
- fromRole: params.role,
101702
- toRole: params.nextRole,
101703
- teamId: params.teamId,
101704
- nativeIntegration: params.nativeIntegration ?? true
102191
+ const { pair, mode } = resolveHandoffTemplateSelection(params, "view-template");
102192
+ const template = renderHandoffTemplate(pair, {
102193
+ nativeIntegration: params.nativeIntegration ?? true,
102194
+ cliEnvPrefix: params.cliEnvPrefix,
102195
+ conversationMode: mode
101705
102196
  });
101706
102197
  if (!template) {
101707
- throw new Error(`No handoff template for ${params.role} → ${params.nextRole}`);
102198
+ throw new HandoffTemplatePairError("UNKNOWN_PAIR", unrenderablePairMessage(pair));
101708
102199
  }
101709
102200
  return template;
101710
102201
  }
101711
102202
  var init_view_template2 = __esm(() => {
101712
- init_architect_handoff_templates();
101713
- init_uiux_engineer_handoff_templates();
101714
102203
  init_handoff_templates3();
102204
+ init_pair();
101715
102205
  });
101716
102206
 
101717
102207
  // src/commands/handoff/view-template.ts
@@ -101720,48 +102210,49 @@ __export(exports_view_template, {
101720
102210
  printHandoffViewTemplate: () => printHandoffViewTemplate
101721
102211
  });
101722
102212
  function printHandoffViewTemplate(options) {
101723
- const template = viewHandoffTemplate({
101724
- role: options.role,
101725
- nextRole: options.nextRole,
101726
- teamId: options.teamId,
101727
- nativeIntegration: true
101728
- });
101729
- console.log(template);
102213
+ try {
102214
+ console.log(viewHandoffTemplate({ ...options, nativeIntegration: true }));
102215
+ } catch (err) {
102216
+ console.error(`❌ ${err.message}`);
102217
+ process.exit(1);
102218
+ }
101730
102219
  }
101731
102220
  var init_view_template3 = __esm(() => {
101732
102221
  init_view_template2();
101733
102222
  });
101734
102223
 
101735
102224
  // ../../services/backend/prompts/cli/handoff-templates/list-templates.ts
101736
- function formatHandoffTemplateListing(listing) {
101737
- const receives = listing.receivesFrom.length ? listing.receivesFrom.map((role) => `\`${role}\``).join(", ") : "(none)";
101738
- const returns = listing.returnsTo.length ? listing.returnsTo.map((role) => `\`${role}\``).join(", ") : "(none)";
101739
- const lines = [
101740
- `Handoff contract for \`${listing.role}\` (team: \`${listing.teamId}\`)`,
101741
- "",
101742
- `Receives from: ${receives}`,
101743
- `Returns to: ${returns}`,
101744
- "",
101745
- "Renderable outbound templates:",
101746
- ...listing.templates.map((template) => `- \`${template.fromRole}\` → \`${template.toRole}\``)
101747
- ];
101748
- return lines.join(`
101749
- `);
101750
- }
101751
102225
  function listHandoffTemplatesCommand(params) {
101752
- const listing = listHandoffTemplates({
101753
- role: params.role,
101754
- teamId: params.teamId,
101755
- cliEnvPrefix: params.cliEnvPrefix
102226
+ const { pair, mode } = resolveHandoffTemplateSelection(params, "list-templates");
102227
+ const reply = getReplyHandoffTemplatePair(pair);
102228
+ const template = renderHandoffTemplate(pair, {
102229
+ nativeIntegration: true,
102230
+ cliEnvPrefix: params.cliEnvPrefix,
102231
+ conversationMode: mode
101756
102232
  });
101757
- if (!listing) {
101758
- const teamId = params.teamId ?? "duo";
101759
- throw new Error(`No handoff contract for role "${params.role}" in team "${teamId}". Known roles: planner, builder (duo) or solo.`);
102233
+ if (!template) {
102234
+ throw new HandoffTemplatePairError("UNKNOWN_PAIR", unrenderablePairMessage(pair));
101760
102235
  }
101761
- return formatHandoffTemplateListing(listing);
102236
+ const sendCommand = handoffCommand({
102237
+ chatroomId: "<chatroom-id>",
102238
+ role: pair.fromRole,
102239
+ nextRole: pair.toRole,
102240
+ cliEnvPrefix: params.cliEnvPrefix ?? ""
102241
+ }).split(`
102242
+ `)[0];
102243
+ return [
102244
+ `Handoff template ${formatHandoffPairLabel(pair)} (team: \`${pair.teamId}\`, mode: \`${mode}\`, key: \`${formatHandoffTemplateKey({ pair, mode })}\`)`,
102245
+ `Send with: ${sendCommand}`,
102246
+ reply ? `Reply pair: ${formatHandoffPairLabel(reply)} (view: ${formatHandoffTemplateCommand("view-template", reply, params.cliEnvPrefix, mode)})` : `Reply pair: none (\`${pair.toRole}\` replies free-form)`,
102247
+ "",
102248
+ template
102249
+ ].join(`
102250
+ `);
101762
102251
  }
101763
102252
  var init_list_templates = __esm(() => {
101764
102253
  init_handoff_templates3();
102254
+ init_pair();
102255
+ init_command2();
101765
102256
  });
101766
102257
 
101767
102258
  // src/commands/handoff/list-templates.ts
@@ -101771,12 +102262,7 @@ __export(exports_list_templates, {
101771
102262
  });
101772
102263
  function printHandoffListTemplates(options) {
101773
102264
  try {
101774
- const output = listHandoffTemplatesCommand({
101775
- role: options.role,
101776
- teamId: options.teamId,
101777
- cliEnvPrefix: options.cliEnvPrefix
101778
- });
101779
- console.log(output);
102265
+ console.log(listHandoffTemplatesCommand(options));
101780
102266
  } catch (err) {
101781
102267
  console.error(`❌ ${err.message}`);
101782
102268
  process.exit(1);
@@ -102071,8 +102557,17 @@ var init_commands_reference = __esm(() => {
102071
102557
  init_command4();
102072
102558
  init_utils3();
102073
102559
  });
102560
+
102561
+ // ../../services/backend/prompts/cli/sections/handoff-template-discovery.ts
102562
+ var init_handoff_template_discovery = __esm(() => {
102563
+ init_handoff_templates3();
102564
+ init_pair();
102565
+ });
102566
+
102074
102567
  // ../../services/backend/prompts/cli/sections/core-responsibilities.ts
102075
- var init_core_responsibilities = () => {};
102568
+ var init_core_responsibilities = __esm(() => {
102569
+ init_handoff_template_discovery();
102570
+ });
102076
102571
  // ../../services/backend/prompts/cli/sections/inter-role-handoff-rule.ts
102077
102572
  function getInterRoleHandoffRule() {
102078
102573
  return [
@@ -102095,6 +102590,7 @@ var init_operating_model = () => {};
102095
102590
  // ../../services/backend/prompts/cli/sections/index.ts
102096
102591
  var init_sections = __esm(() => {
102097
102592
  init_core_responsibilities();
102593
+ init_handoff_template_discovery();
102098
102594
  init_handoff_rules();
102099
102595
  init_proof_of_verification2();
102100
102596
  init_operating_model();
@@ -102118,13 +102614,13 @@ ${getInterRoleHandoffRule()}
102118
102614
  4. Analyze concurrent writers and races, idempotency, ordering/monotonicity, retries, transactions, failure/recovery, primary read paths, indexes, projections/read models, query shapes, scan/transaction limits, and invalidation/subscription scope.
102119
102615
  5. Account for Convex reactivity and bandwidth: avoid unnecessary reactive fanout and separate high-frequency heartbeat/liveness/status fields from low-frequency identity/configuration fields. Specify migration/backfill sequence, tests, acceptance criteria, and the implementation and verification sequence.
102120
102616
  6. Keep the proposal within the user's request and the repository's established patterns. Do not expand scope, spawn subagents, implement the design, edit files, or act as the builder.
102121
- 7. Hand the complete design brief to the configured entry point with the normal command, then stop:
102617
+ 7. Hand the complete design brief to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102122
102618
 
102123
102619
  \`\`\`bash
102124
102620
  chatroom handoff --chatroom-id="<chatroom-id>" --role="architect" --next-role="{ENTRY_POINT_ROLE}"
102125
102621
  \`\`\`
102126
102622
 
102127
- The handoff must contain every required brief section, repository evidence, chosen design, exact file/API/schema details, risks, acceptance criteria, tests, and implementation sequence the configured entry point needs to coordinate implementation. It must not contain implementation edits or alternative designs.`;
102623
+ The handoff must contain every required brief section, repository evidence, chosen design, exact file/API/schema details, risks, acceptance criteria, tests, and implementation sequence \`{ENTRY_POINT_ROLE}\` needs to coordinate implementation. It must not contain implementation edits or alternative designs.`;
102128
102624
  });
102129
102625
 
102130
102626
  // ../../services/backend/prompts/cli/roles/builder.ts
@@ -102156,20 +102652,44 @@ ${getInterRoleHandoffRule()}
102156
102652
  4. Label every finding \`confirmed\`, \`inferred\`, or \`unknown\`. Never present a guess as fact.
102157
102653
  5. Resolve ambiguity where evidence allows. For the rest, state the open question, who must decide it, and a recommended default.
102158
102654
  6. Follow the injected \`<handoff-templates>\` research brief exactly, in its order. Answer only the questions asked. Do not present alternative architectures beyond what grounds the decision.
102159
- 7. Hand the brief to the configured entry point with the normal command, then stop:
102655
+ 7. Hand the brief to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102160
102656
 
102161
102657
  \`\`\`bash
102162
102658
  chatroom handoff --chatroom-id="<chatroom-id>" --role="researcher" --next-role="{ENTRY_POINT_ROLE}"
102163
102659
  \`\`\``;
102164
102660
  });
102165
102661
 
102662
+ // ../../services/backend/prompts/cli/roles/reviewer.ts
102663
+ var REVIEWER_GUIDANCE;
102664
+ var init_reviewer2 = __esm(() => {
102665
+ init_sections();
102666
+ REVIEWER_GUIDANCE = `## Reviewer Operating Model
102667
+
102668
+ You are the reviewer responsible for inspecting the code artifacts the planner names and reporting the issues you observe. You are advisory only: do not edit files, implement fixes, or act as the builder or planner.
102669
+
102670
+ ${"{SESSION_CONTINUITY}"}
102671
+
102672
+ ${getInterRoleHandoffRule()}
102673
+
102674
+ 1. Recover the review target and focus from the injected task and the \`<handoff-templates>\` brief. If the target is not explicit, ask the planner through the handoff; do not guess a range.
102675
+ 2. Inspect the target: the diff or commits, the changed files, and the surrounding code they depend on. Read the actual files; do not review from summaries.
102676
+ 3. Look for correctness bugs, security issues, missing or weak tests, unclear ownership or error handling, dead code, duplication, and type drift. Stay within the stated focus when one is given.
102677
+ 4. Label every issue with a severity (\`blocker\`, \`major\`, \`minor\`, \`nit\`) and cite the file and line. Only report what you observed; mark anything unverified as such.
102678
+ 5. Follow the injected \`<handoff-templates>\` review report exactly, in its order.
102679
+ 6. Hand the report to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102680
+
102681
+ \`\`\`bash
102682
+ chatroom handoff --chatroom-id="<chatroom-id>" --role="reviewer" --next-role="{ENTRY_POINT_ROLE}"
102683
+ \`\`\``;
102684
+ });
102685
+
102166
102686
  // ../../services/backend/prompts/cli/roles/triage.ts
102167
102687
  var TRIAGE_GUIDANCE;
102168
102688
  var init_triage3 = __esm(() => {
102169
102689
  init_sections();
102170
102690
  TRIAGE_GUIDANCE = `## Triage Operating Model
102171
102691
 
102172
- You are the triage agent responsible for investigating a reported bug so the entry point can delegate a precise fix. You are advisory only: do not edit implementation files or implement the fix.
102692
+ You are the triage agent responsible for investigating a reported bug so the recipient can delegate a precise fix. You are advisory only: do not edit implementation files or implement the fix.
102173
102693
 
102174
102694
  ${"{SESSION_CONTINUITY}"}
102175
102695
 
@@ -102179,7 +102699,7 @@ ${getInterRoleHandoffRule()}
102179
102699
  2. Trace the relevant code paths with concrete repository paths and symbols. Label every finding \`confirmed\` or \`hypothesis\`. Never present a hypothesis as fact.
102180
102700
  3. Attempt a focused reproduction only when it is cheap and safe. A focused regression test may be written as evidence. Do not edit implementation files.
102181
102701
  4. Write the report using the sections in the injected \`<handoff-templates>\`, in the order given, beginning with the \`## Summary\` section.
102182
- 5. Hand the report to the configured entry point with the normal command, then stop:
102702
+ 5. Hand the report to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102183
102703
 
102184
102704
  \`\`\`bash
102185
102705
  chatroom handoff --chatroom-id="<chatroom-id>" --role="triage" --next-role="{ENTRY_POINT_ROLE}"
@@ -102204,20 +102724,19 @@ ${getInterRoleHandoffRule()}
102204
102724
  4. Specify exact keyboard shortcuts, focus order, keyboard navigation, focus restoration, accessible semantics and labels, component hierarchy and ownership, props/state/events, data boundaries, and interaction behavior.
102205
102725
  5. Choose concrete ShadCN components using the Base UI backend and existing icon conventions. Specify exact Tailwind utility or semantic theme-token classes for layout, spacing, sizing, typography, states, responsive behavior, and dark mode; keep the styling theme-aware and make state ownership explicit. Also specify responsive breakpoints, visual feedback, destructive-action safeguards, and the UI/integration/accessibility test plan.
102206
102726
  6. Keep the proposal within the user's request and the repository's established patterns. Do not expand scope, spawn subagents, implement the design, edit files, or act as the builder.
102207
- 7. Hand the complete design brief to the configured entry point with the normal command, then stop:
102727
+ 7. Hand the complete design brief to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102208
102728
 
102209
102729
  \`\`\`bash
102210
102730
  chatroom handoff --chatroom-id="<chatroom-id>" --role="uiux-engineer" --next-role="{ENTRY_POINT_ROLE}"
102211
102731
  \`\`\`
102212
102732
 
102213
- The handoff must contain every required brief section, repository evidence, chosen flow, exact component/prop/state details, explicit states, accessibility details, ownership decisions, concrete classes/tokens, risks, acceptance criteria, tests, and implementation sequence the configured entry point needs to coordinate implementation. It must not contain implementation edits or alternative designs.`;
102733
+ The handoff must contain every required brief section, repository evidence, chosen flow, exact component/prop/state details, explicit states, accessibility details, ownership decisions, concrete classes/tokens, risks, acceptance criteria, tests, and implementation sequence \`{ENTRY_POINT_ROLE}\` needs to coordinate implementation. It must not contain implementation edits or alternative designs.`;
102214
102734
  });
102215
102735
 
102216
102736
  // ../../services/backend/prompts/cli/roles/verifier.ts
102217
102737
  var ACHIEVED2, NOT_ACHIEVED2, INCONCLUSIVE2, VERIFIER_GUIDANCE;
102218
102738
  var init_verifier3 = __esm(() => {
102219
102739
  init_verifier_handoff_templates();
102220
- init_chat_handoff_template();
102221
102740
  init_handoff_report_template_body();
102222
102741
  init_sections();
102223
102742
  [ACHIEVED2, NOT_ACHIEVED2, INCONCLUSIVE2] = VERIFIER_VERDICTS;
@@ -102237,7 +102756,7 @@ ${getInterRoleHandoffRule()}
102237
102756
  4a. User expectations: the user's handoff template defines what the user expects from the work. In a code mode, turn each applicable item that concerns the work into a user expectation: each requirement's evidence (PR, commit, or file), files changed, Code Change Verification, backlog items moved to \`pending_user_review\` after a verified end-to-end feature with a PR, and any manual steps or unresolved decisions the user must act on. Skip presentation-only items: template disclosure checkboxes, section order, collapsing, diagram format, and Proof of Planning. In \`chat\` mode the template asks only for a direct, concise answer, so add no expectations beyond the requirements.
102238
102757
  5. Find evidence for every requirement in the logs alone: builder handoff reports, planner delegations, quoted test output, commits, and PRs. \`met\` requires concrete evidence in the logs. The planner's claimed outcome is a claim, not evidence. Silence means \`unverified\`. A contradiction, or a log showing the requirement was not done, means \`unmet\`. Never state that tests passed unless a log reports it, or you ran the requested tests yourself.
102239
102758
  6. Choose exactly one verdict from ${VERIFIER_VERDICTS.join(", ")}: ${ACHIEVED2} only if every requirement and every user expectation is met; ${NOT_ACHIEVED2} if any requirement or user expectation is unmet; ${INCONCLUSIVE2} if none is unmet but any is unverified.
102240
- 7. Follow the injected \`<handoff-templates>\` verdict template exactly, in its order, and put the complete verdict in the handoff. Then hand off to the configured entry point with the normal command, then stop:
102759
+ 7. Follow the injected \`<handoff-templates>\` verdict template exactly, in its order, and put the complete verdict in the handoff. Then hand off to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102241
102760
 
102242
102761
  \`\`\`bash
102243
102762
  chatroom handoff --chatroom-id="<chatroom-id>" --role="verifier" --next-role="{ENTRY_POINT_ROLE}"
@@ -102266,10 +102785,12 @@ var init_fromContext2 = __esm(() => {
102266
102785
  init_builder2();
102267
102786
  init_planner2();
102268
102787
  init_researcher2();
102788
+ init_reviewer2();
102269
102789
  init_triage3();
102270
102790
  init_uiux_engineer3();
102271
102791
  init_verifier3();
102272
102792
  init_fromContext();
102793
+ init_handoff_templates3();
102273
102794
  });
102274
102795
 
102275
102796
  // ../../services/backend/prompts/teams/duo/prompts/builder.ts
@@ -102358,6 +102879,19 @@ var init_templates = __esm(() => {
102358
102879
  ],
102359
102880
  defaultHandoffTarget: "planner"
102360
102881
  },
102882
+ reviewer: {
102883
+ role: "reviewer",
102884
+ title: "Reviewer",
102885
+ description: "You are the reviewer responsible for inspecting the code artifacts the planner names and reporting the issues you observe; you are advisory only and do not implement fixes.",
102886
+ responsibilities: [
102887
+ "Recover the review target and focus from the planner brief",
102888
+ "Inspect the diff or commits and the surrounding code they depend on",
102889
+ "Look for correctness, security, test quality, ownership, dead code, duplication, and type drift",
102890
+ "Label each issue with a severity and cite the file and line",
102891
+ "Hand one review report to the planner, separating reviewed scope from what was not reviewed"
102892
+ ],
102893
+ defaultHandoffTarget: "planner"
102894
+ },
102361
102895
  verifier: {
102362
102896
  role: "verifier",
102363
102897
  title: "Verifier",
@@ -102381,7 +102915,7 @@ var init_templates = __esm(() => {
102381
102915
  "Attempt to reproduce the issue with the smallest focused automated test and report the result honestly",
102382
102916
  "Recommend the smallest immediate fix without implementing it",
102383
102917
  "Report systemic design risks separately from the immediate fix",
102384
- "Hand the complete investigation report to the configured entry point"
102918
+ "Hand the complete investigation report to the planner"
102385
102919
  ],
102386
102920
  defaultHandoffTarget: "planner"
102387
102921
  },
@@ -138304,37 +138838,29 @@ teamCommand.command("set").description("Set the team preset for a chatroom").req
138304
138838
  const { setTeam: setTeam2 } = await Promise.resolve().then(() => (init_team(), exports_team));
138305
138839
  await setTeam2(options.chatroomId, options.team);
138306
138840
  });
138307
- handoffCommandGroup.command("view-template").description("Print a handoff message template; omit --next-role to inspect a generic architect or UI/UX engineer template").option("--team-id <teamId>", "Team id (solo, duo); defaults to duo").action(async function(options) {
138841
+ handoffCommandGroup.command("view-template").description("Print the handoff template for one sender → recipient pair in one conversation mode (requires --from, --to, and --mode)").option("--from <role>", "Sending role (the role that runs the handoff)").option("--to <role>", "Receiving role (the --next-role of the handoff)").option("--mode <mode>", "Conversation mode: chat | code | code:enhanced (required)").option("--team-id <teamId>", "Team id (solo, duo); defaults to duo").action(async function(options) {
138308
138842
  const parentOpts = this.parent?.opts() ?? {};
138309
- if (!parentOpts.role) {
138310
- console.error(`error: required option '--role <role>' not specified`);
138311
- process.exit(1);
138312
- }
138313
138843
  const { printHandoffViewTemplate: printHandoffViewTemplate2 } = await Promise.resolve().then(() => (init_view_template3(), exports_view_template));
138314
- try {
138315
- printHandoffViewTemplate2({
138316
- role: parentOpts.role,
138317
- nextRole: parentOpts.nextRole,
138318
- teamId: options.teamId
138319
- });
138320
- } catch (err) {
138321
- console.error(`❌ ${err.message}`);
138322
- process.exit(1);
138323
- }
138844
+ printHandoffViewTemplate2({
138845
+ from: options.from,
138846
+ to: options.to,
138847
+ mode: options.mode,
138848
+ teamId: options.teamId,
138849
+ legacyRole: parentOpts.role,
138850
+ legacyNextRole: parentOpts.nextRole
138851
+ });
138324
138852
  });
138325
- handoffCommandGroup.command("list-templates").description("List the role-owned handoff contract and renderable templates (static, no chatroom required)").option("--team-id <teamId>", "Team id (solo, duo); defaults to duo").action(async function(options) {
138853
+ handoffCommandGroup.command("list-templates").description("Show the pair descriptor and handoff template for one sender → recipient pair in one conversation mode (requires --from, --to, and --mode; static, no chatroom required)").option("--from <role>", "Sending role (the role that runs the handoff)").option("--to <role>", "Receiving role (the --next-role of the handoff)").option("--mode <mode>", "Conversation mode: chat | code | code:enhanced (required)").option("--team-id <teamId>", "Team id (solo, duo); defaults to duo").action(async function(options) {
138326
138854
  const parentOpts = this.parent?.opts() ?? {};
138327
- if (!parentOpts.role) {
138328
- console.error(`error: required option '--role <role>' not specified`);
138329
- process.exit(1);
138330
- }
138331
138855
  const { printHandoffListTemplates: printHandoffListTemplates2 } = await Promise.resolve().then(() => (init_list_templates2(), exports_list_templates));
138332
- try {
138333
- printHandoffListTemplates2({ role: parentOpts.role, teamId: options.teamId });
138334
- } catch (err) {
138335
- console.error(`❌ ${err.message}`);
138336
- process.exit(1);
138337
- }
138856
+ printHandoffListTemplates2({
138857
+ from: options.from,
138858
+ to: options.to,
138859
+ mode: options.mode,
138860
+ teamId: options.teamId,
138861
+ legacyRole: parentOpts.role,
138862
+ legacyNextRole: parentOpts.nextRole
138863
+ });
138338
138864
  });
138339
138865
  handoffCommandGroup.option("--chatroom-id <id>", "Chatroom identifier").option("--role <role>", "Your role").option("--next-role <nextRole>", "Role to hand off to").action(async (options) => {
138340
138866
  const missing = [
@@ -138776,4 +139302,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
138776
139302
  });
138777
139303
  program2.parse();
138778
139304
 
138779
- //# debugId=BF04636703AF51D164756E2164756E21
139305
+ //# debugId=BCEF986EF291738664756E2164756E21