chatroom-cli 1.131.1 → 1.132.0

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.
package/dist/index.js CHANGED
@@ -100231,6 +100231,119 @@ var init_agent2 = __esm(() => {
100231
100231
  init_storage2();
100232
100232
  });
100233
100233
 
100234
+ // ../../services/backend/prompts/cli/handoff-templates/pair.ts
100235
+ function normalizeHandoffRole(value2) {
100236
+ if (value2 === undefined)
100237
+ return;
100238
+ const normalized = value2.trim().toLowerCase();
100239
+ return normalized === "" ? undefined : normalized;
100240
+ }
100241
+ function normalizeHandoffMode(value2) {
100242
+ if (value2 === undefined)
100243
+ return;
100244
+ const normalized = value2.trim().toLowerCase();
100245
+ return normalized === "" ? undefined : normalized;
100246
+ }
100247
+ function isConversationMode2(value2) {
100248
+ return CONVERSATION_MODES.includes(value2);
100249
+ }
100250
+ function modeBucket(mode) {
100251
+ return mode === "chat" ? "chat" : "code";
100252
+ }
100253
+ function formatHandoffTemplateKey(selection) {
100254
+ const { pair, mode } = selection;
100255
+ return `${pair.teamId}:${pair.fromRole}->${pair.toRole}@${modeBucket(mode)}`;
100256
+ }
100257
+ function isTeamPresetId(value2) {
100258
+ return TEAM_PRESET_IDS.includes(value2);
100259
+ }
100260
+ function formatHandoffPairLabel(pair) {
100261
+ return `\`${pair.fromRole}\` → \`${pair.toRole}\``;
100262
+ }
100263
+ function formatHandoffTemplateCommand(command, pair, cliEnvPrefix = "", modeArg) {
100264
+ const modeFlag = modeArg === undefined ? "" : ` --mode="${modeArg}"`;
100265
+ return `${cliEnvPrefix}chatroom handoff ${command} --from="${pair.fromRole}" --to="${pair.toRole}"${modeFlag} --team-id="${pair.teamId}"`;
100266
+ }
100267
+ function missingPairMessage(command, missing) {
100268
+ return [
100269
+ `handoff ${command} requires both --from and --to (missing: ${missing}). Handoff templates are keyed by the (sender, recipient) pair.`,
100270
+ `Example: chatroom handoff ${command} --from="planner" --to="builder" --mode="code" --team-id="duo"`
100271
+ ].join(`
100272
+ `);
100273
+ }
100274
+ function missingModeMessage(command) {
100275
+ return [
100276
+ `handoff ${command} requires --mode (missing: --mode). Handoff templates are keyed by the (sender, recipient) pair and the conversation mode.`,
100277
+ `Example: chatroom handoff ${command} --from="planner" --to="user" --mode="chat" --team-id="duo"`
100278
+ ].join(`
100279
+ `);
100280
+ }
100281
+ function unknownModeMessage(mode) {
100282
+ return `Unknown mode "${mode}". Valid modes: ${CONVERSATION_MODES.join(", ")}.`;
100283
+ }
100284
+ function legacyRoleFlagsMessage(command, input) {
100285
+ const header = `handoff ${command} no longer accepts --role/--next-role. Handoff templates are keyed by the (sender, recipient) pair.`;
100286
+ const modeArg = input.mode ?? "<chat|code|code:enhanced>";
100287
+ if (input.legacyRole !== undefined && input.legacyNextRole !== undefined) {
100288
+ return [
100289
+ header,
100290
+ `Use: ${formatHandoffTemplateCommand(command, {
100291
+ teamId: input.teamId,
100292
+ fromRole: input.legacyRole,
100293
+ toRole: input.legacyNextRole
100294
+ }, "", modeArg)}`
100295
+ ].join(`
100296
+ `);
100297
+ }
100298
+ if (input.legacyRole !== undefined && input.rolePairs && input.rolePairs.length > 0) {
100299
+ return [
100300
+ header,
100301
+ `Pairs from "${input.legacyRole}" in team "${input.teamId}":`,
100302
+ ...input.rolePairs.map((pair) => ` ${formatHandoffTemplateCommand(command, pair, "", modeArg)}`)
100303
+ ].join(`
100304
+ `);
100305
+ }
100306
+ const to = input.legacyNextRole ?? "<recipient-role>";
100307
+ return [
100308
+ header,
100309
+ `Use: chatroom handoff ${command} --from="<your-role>" --to="${to}" --mode="${modeArg}" --team-id="${input.teamId}"`
100310
+ ].join(`
100311
+ `);
100312
+ }
100313
+ function unknownTeamMessage(team) {
100314
+ return `Unknown team "${team}". Known teams: ${TEAM_PRESET_IDS.join(", ")}.`;
100315
+ }
100316
+ function unknownFromRoleMessage(input) {
100317
+ return `Role "${input.from}" has no handoff templates in team "${input.team}". Roles with handoff templates: ${input.roles.join(", ")}.`;
100318
+ }
100319
+ function unknownPairMessage(input) {
100320
+ return `No handoff template for "${input.from}" → "${input.to}" in team "${input.team}". Valid recipients for "${input.from}": ${input.recipients.join(", ")}.`;
100321
+ }
100322
+ function unrenderablePairMessage(pair) {
100323
+ return `No handoff template for "${pair.fromRole}" → "${pair.toRole}" in team "${pair.teamId}".`;
100324
+ }
100325
+ var HandoffTemplatePairError, DEFAULT_HANDOFF_TEAM_ID = "duo";
100326
+ var init_pair = __esm(() => {
100327
+ init_conversation_mode();
100328
+ init_team_kind();
100329
+ HandoffTemplatePairError = class HandoffTemplatePairError extends Error {
100330
+ code;
100331
+ constructor(code2, message) {
100332
+ super(message);
100333
+ this.code = code2;
100334
+ this.name = "HandoffTemplatePairError";
100335
+ }
100336
+ };
100337
+ });
100338
+
100339
+ // ../../services/backend/prompts/native/handoff-visibility.ts
100340
+ function getHandoffRecipientVisibilityCallout(toRole) {
100341
+ const recipient = toRole.toLowerCase() === "user" ? "user" : `\`${toRole}\` agent`;
100342
+ const sendCommand = `\`handoff --next-role="${toRole}"\``;
100343
+ return `> ⚠️ **Template notice — not part of the message. Do not copy this notice into your handoff.**
100344
+ > 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.`;
100345
+ }
100346
+
100234
100347
  // ../../services/backend/prompts/cli/handoff/command.ts
100235
100348
  function handoffCommand(params) {
100236
100349
  const prefix = params.cliEnvPrefix || "";
@@ -100247,39 +100360,6 @@ var init_command2 = __esm(() => {
100247
100360
  init_stdin_heredoc();
100248
100361
  });
100249
100362
 
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
100363
  // ../../services/backend/prompts/utils/file-reference-guidance.ts
100284
100364
  function getFileReferenceGuidanceComment() {
100285
100365
  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 +100370,6 @@ function getFileReferenceProofOfCompletionExample() {
100290
100370
  }
100291
100371
 
100292
100372
  // ../../services/backend/prompts/teams/architect-handoff-templates.ts
100293
- function normalizeEntryPointRole(entryPointRole) {
100294
- return entryPointRole.trim().toLowerCase() || "planner";
100295
- }
100296
100373
  function getArchitectFocus() {
100297
100374
  return "module boundaries, APIs, schemas, indexes and queries, invariants, failure and recovery handling, tests, and implementation sequence";
100298
100375
  }
@@ -100305,13 +100382,9 @@ function getArchitectRequirements() {
100305
100382
  - 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
100383
  - Specify concrete schema, query, and mutation changes; migration/backfill sequence; tests; and verification order.`;
100307
100384
  }
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.
100385
+ function getEntryPointToArchitectHandoffTemplate(query) {
100386
+ const entryPoint = query.fromRole;
100387
+ 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
100388
 
100316
100389
  Provide the request, relevant constraints, and the files or product surfaces that need inspection. Ask for one evidence-backed design focused on ${getArchitectFocus()}.
100317
100390
 
@@ -100326,20 +100399,10 @@ ${handoffCommand({
100326
100399
  })}
100327
100400
  \`\`\``;
100328
100401
  }
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.
100402
+ function getArchitectToEntryPointHandoffTemplate(query) {
100403
+ const entryPoint = query.toRole;
100404
+ const sharedContractsHeading = `## Shared contracts (${entryPoint}-owned)`;
100405
+ 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
100406
 
100344
100407
  ## Summary
100345
100408
  <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 +100450,7 @@ ${sharedContractsHeading}
100387
100450
  ## Requirements (acceptance criteria)
100388
100451
  - <one concrete, verifiable requirement per bullet; include exact data shape, API contract, migration result, and failure behavior>
100389
100452
  - 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.
100453
+ - Verify the implemented user-facing feature or task-delivery path end-to-end; unit tests alone are insufficient.
100391
100454
 
100392
100455
  ## What to avoid
100393
100456
  - Do not implement code or edit files as the architect; this handoff is advisory only.
@@ -100401,8 +100464,7 @@ ${sharedContractsHeading}
100401
100464
  ## Out of scope
100402
100465
  - <explicit files, flows, behavior, or migration work the implementer must not touch>
100403
100466
 
100404
- ## Handoff
100405
- Run the normal handoff command to the configured entry point with this complete design, then stop.${placeholderInstruction}
100467
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100406
100468
 
100407
100469
  \`\`\`bash
100408
100470
  ${handoffCommand({
@@ -100417,145 +100479,162 @@ var init_architect_handoff_templates = __esm(() => {
100417
100479
  init_command2();
100418
100480
  });
100419
100481
 
100420
- // ../../services/backend/prompts/teams/uiux-engineer-handoff-templates.ts
100421
- function normalizeEntryPointRole2(entryPointRole) {
100422
- return entryPointRole.trim().toLowerCase() || "planner";
100482
+ // ../../services/backend/prompts/teams/duo/handoff-templates/architect-planner-code.ts
100483
+ function getArchitectPlannerCodeTemplate(query) {
100484
+ return getArchitectToEntryPointHandoffTemplate(query);
100423
100485
  }
100424
- function getUiuxEngineerFocus() {
100425
- return "complete user flows, loading/empty/error/success states, component ownership, theme tokens and layout, responsive details, and UI tests";
100426
- }
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.
100486
+ var init_architect_planner_code = __esm(() => {
100487
+ init_architect_handoff_templates();
100488
+ });
100444
100489
 
100445
- Provide the request, relevant constraints, and the files or product surfaces that need inspection. Ask for one evidence-backed design focused on ${getUiuxEngineerFocus()}.
100490
+ // ../../services/backend/prompts/teams/duo/handoff-templates/architect-planner-chat.ts
100491
+ var init_architect_planner_chat = __esm(() => {
100492
+ init_architect_planner_code();
100493
+ });
100446
100494
 
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.
100495
+ // ../shared/src/domain/chatroom-role.ts
100496
+ var CHATROOM_ROLE_USER = "user";
100497
+ var init_chatroom_role = __esm(() => {
100498
+ init_agent_role();
100499
+ });
100448
100500
 
100449
- \`\`\`bash
100450
- ${handoffCommand({
100451
- chatroomId: "<chatroom-id>",
100452
- role: "uiux-engineer",
100453
- nextRole: entryPoint,
100454
- cliEnvPrefix: ""
100455
- })}
100456
- \`\`\``;
100501
+ // ../../services/backend/prompts/cli/handoff-templates/contracts.ts
100502
+ function handoffTemplateByMode(getters) {
100503
+ return (query) => query.conversationMode === "chat" ? getters.chat(query) : getters.code(query);
100504
+ }
100505
+ function validateRoleHandoffContracts(contracts) {
100506
+ const byRole = new Map;
100507
+ for (const contract of contracts) {
100508
+ const key = contract.role.toLowerCase();
100509
+ if (byRole.has(key)) {
100510
+ throw new Error(`Duplicate role handoff contract: "${contract.role}"`);
100511
+ }
100512
+ byRole.set(key, contract);
100513
+ }
100514
+ for (const contract of contracts) {
100515
+ const ownerKey = contract.role.toLowerCase();
100516
+ for (const target of Object.keys(contract.outboundTemplates)) {
100517
+ const targetKey = target.toLowerCase();
100518
+ if (targetKey === "user")
100519
+ continue;
100520
+ const targetContract = byRole.get(targetKey);
100521
+ if (!targetContract) {
100522
+ throw new Error(`Role "${contract.role}" declares an outbound template to "${target}", which is neither 'user' nor a role listed in the catalogue`);
100523
+ }
100524
+ const declaresOwner = (targetContract.receivesFrom ?? []).some((from) => from.toLowerCase() === ownerKey);
100525
+ if (!declaresOwner) {
100526
+ 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`);
100527
+ }
100528
+ }
100529
+ }
100530
+ }
100531
+ function validateBuiltinOwners(teamName, expectedRoles, contracts) {
100532
+ const actualRoles = new Set;
100533
+ const byRole = new Map;
100534
+ for (const contract of contracts) {
100535
+ const normalizedOwner = contract.role.trim().toLowerCase();
100536
+ if (!normalizedOwner || contract.role !== normalizedOwner) {
100537
+ throw new Error(`${teamName} handoff owner "${contract.role}" is not canonical`);
100538
+ }
100539
+ if (actualRoles.has(normalizedOwner)) {
100540
+ throw new Error(`${teamName} has duplicate handoff contract owner "${contract.role}"`);
100541
+ }
100542
+ if (!expectedRoles.has(normalizedOwner)) {
100543
+ throw new Error(`${teamName} has unexpected handoff contract role "${contract.role}"`);
100544
+ }
100545
+ actualRoles.add(normalizedOwner);
100546
+ byRole.set(normalizedOwner, contract);
100547
+ }
100548
+ for (const role of expectedRoles) {
100549
+ if (!actualRoles.has(role)) {
100550
+ throw new Error(`${teamName} is missing handoff contract for role "${role}"`);
100551
+ }
100552
+ }
100553
+ return byRole;
100457
100554
  }
100458
- function getUiuxEngineerToEntryPointHandoffTemplate(entryPointRole) {
100459
- return renderUiuxEngineerToEntryPointHandoffTemplate(normalizeEntryPointRole2(entryPointRole));
100555
+ function validateReferenceTargets(teamName, owner, label, targets, allowedTargets) {
100556
+ const seen = new Set;
100557
+ for (const target of targets) {
100558
+ const normalizedTarget = target.trim().toLowerCase();
100559
+ if (target !== normalizedTarget || !allowedTargets.has(normalizedTarget)) {
100560
+ throw new Error(`${teamName} role "${owner}" has invalid ${label} target "${target}"`);
100561
+ }
100562
+ if (seen.has(normalizedTarget)) {
100563
+ throw new Error(`${teamName} role "${owner}" has duplicate ${label} target "${target}"`);
100564
+ }
100565
+ seen.add(normalizedTarget);
100566
+ }
100460
100567
  }
100461
- function getGenericUiuxEngineerToEntryPointHandoffTemplate() {
100462
- return renderUiuxEngineerToEntryPointHandoffTemplate("<entry-point-role>", true);
100568
+ function validateBuiltinReferences(teamName, allowedTargets, contracts) {
100569
+ for (const contract of contracts) {
100570
+ const owner = contract.role;
100571
+ validateReferenceTargets(teamName, owner, "receivesFrom", contract.receivesFrom, allowedTargets);
100572
+ validateReferenceTargets(teamName, owner, "returnsTo", contract.returnsTo, allowedTargets);
100573
+ const outboundTargets = Object.keys(contract.outboundTemplates);
100574
+ if (outboundTargets.length === 0) {
100575
+ throw new Error(`${teamName} role "${owner}" must have an outbound handoff capability`);
100576
+ }
100577
+ const returnsTo = new Set(contract.returnsTo);
100578
+ const outbound = new Set(outboundTargets);
100579
+ validateReferenceTargets(teamName, owner, "outbound", outboundTargets, allowedTargets);
100580
+ for (const target of outboundTargets) {
100581
+ if (typeof contract.outboundTemplates[target] !== "function") {
100582
+ throw new Error(`${teamName} role "${owner}" has no outbound getter for target "${target}"`);
100583
+ }
100584
+ }
100585
+ if (returnsTo.size !== outbound.size || [...returnsTo].some((target) => !outbound.has(target))) {
100586
+ throw new Error(`${teamName} role "${owner}" returnsTo targets must exactly match outbound targets`);
100587
+ }
100588
+ }
100463
100589
  }
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
- \`\`\``;
100590
+ function validateBuiltinReciprocity(teamName, byRole, contracts) {
100591
+ for (const contract of contracts) {
100592
+ const owner = contract.role;
100593
+ for (const receivedFrom of contract.receivesFrom) {
100594
+ if (receivedFrom === CHATROOM_ROLE_USER)
100595
+ continue;
100596
+ const source = byRole.get(receivedFrom);
100597
+ if (!source?.outboundTemplates[owner]) {
100598
+ throw new Error(`${teamName} role "${owner}" receives from "${receivedFrom}" without a reverse outbound edge`);
100599
+ }
100600
+ }
100601
+ }
100602
+ try {
100603
+ validateRoleHandoffContracts(contracts);
100604
+ } catch (error51) {
100605
+ const contextualError = new Error(`${teamName}: ${error51 instanceof Error ? error51.message : String(error51)}`);
100606
+ Object.defineProperty(contextualError, "cause", { value: error51, configurable: true });
100607
+ throw contextualError;
100608
+ }
100544
100609
  }
100545
- var init_uiux_engineer_handoff_templates = __esm(() => {
100546
- init_command2();
100610
+ function validateBuiltinTeamRoleHandoffContracts(teamId, contracts) {
100611
+ const teamName = TEAM_PRESETS[teamId].name;
100612
+ const expectedRoles = new Set(TEAM_PRESETS[teamId].roles);
100613
+ const byRole = validateBuiltinOwners(teamName, expectedRoles, contracts);
100614
+ const allowedTargets = new Set([...expectedRoles, CHATROOM_ROLE_USER]);
100615
+ validateBuiltinReferences(teamName, allowedTargets, contracts);
100616
+ validateBuiltinReciprocity(teamName, byRole, contracts);
100617
+ }
100618
+ var init_contracts = __esm(() => {
100619
+ init_chatroom_role();
100620
+ init_team_presets();
100547
100621
  });
100548
100622
 
100549
100623
  // ../../services/backend/prompts/teams/duo/handoff-templates/architect.ts
100550
100624
  var duoArchitectHandoffContract;
100551
100625
  var init_architect = __esm(() => {
100552
- init_architect_handoff_templates();
100626
+ init_architect_planner_chat();
100627
+ init_architect_planner_code();
100628
+ init_contracts();
100553
100629
  duoArchitectHandoffContract = {
100554
100630
  role: "architect",
100555
100631
  receivesFrom: ["planner"],
100556
100632
  returnsTo: ["planner"],
100557
100633
  outboundTemplates: {
100558
- planner: () => getArchitectToEntryPointHandoffTemplate("planner")
100634
+ planner: handoffTemplateByMode({
100635
+ chat: getArchitectPlannerCodeTemplate,
100636
+ code: getArchitectPlannerCodeTemplate
100637
+ })
100559
100638
  }
100560
100639
  };
100561
100640
  });
@@ -100577,13 +100656,16 @@ var DELEGATION_BRIEF_DISCLOSURE_CHECKBOX = "- [ ] I confirm the delegation brief
100577
100656
  function getHandoffNotApplicableSectionComment(context3) {
100578
100657
  return `<!-- REQUIRED. ${context3}, or write exactly "${HANDOFF_NOT_APPLICABLE_EXACT_TEXT}" with no explanation. Do not omit this section. -->`;
100579
100658
  }
100580
- function getHandoffReportTemplateIntro(templateLabel) {
100581
- return `**${templateLabel}** — complete every section below. Do not omit sections, principles, or XML wrappers:
100659
+ function getHandoffTemplateTitleLine(pair) {
100660
+ 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):`;
100661
+ }
100662
+ function getHandoffReportTemplateIntro() {
100663
+ return `Instructions (not part of the message): complete every section below. Do not omit sections, principles, or XML wrappers.
100582
100664
 
100583
100665
  When a section has no content, write exactly \`${HANDOFF_NOT_APPLICABLE_EXACT_TEXT}\` — no explanation, no em-dash, no additional text.`;
100584
100666
  }
100585
100667
  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.`;
100668
+ 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
100669
  }
100588
100670
  var HANDOFF_NOT_APPLICABLE_EXACT_TEXT = "Not Applicable.";
100589
100671
 
@@ -100657,11 +100739,9 @@ ${getRoleGuidanceDisclosureComment(params)}`;
100657
100739
  var ROLE_GUIDANCE_DISCLOSURE_CHECKBOX = "- [ ] I confirm that I've read and followed the role guidance before starting any work";
100658
100740
  var init_role_guidance_disclosure = () => {};
100659
100741
 
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)")}
100742
+ // ../../services/backend/prompts/teams/duo/handoff-templates/builder-planner-code.ts
100743
+ function getBuilderPlannerCodeBody(roleGuidanceContext) {
100744
+ return `${getHandoffReportTemplateIntro()}
100665
100745
 
100666
100746
  \`\`\`markdown
100667
100747
  ## Summary
@@ -100690,34 +100770,58 @@ ${getHandoffNotApplicableSectionComment("List review notes")}
100690
100770
  <specific areas for planner to check>
100691
100771
  \`\`\``;
100692
100772
  }
100693
- var init_builder_to_planner = __esm(() => {
100773
+ function getBuilderPlannerCodeTemplate(query) {
100774
+ return getBuilderPlannerCodeBody({
100775
+ chatroomId: query.chatroomId,
100776
+ role: query.role,
100777
+ cliEnvPrefix: query.cliEnvPrefix
100778
+ });
100779
+ }
100780
+ var init_builder_planner_code = __esm(() => {
100694
100781
  init_handoff_quality_principles();
100695
100782
  init_role_guidance_disclosure();
100696
100783
  });
100697
100784
 
100785
+ // ../../services/backend/prompts/teams/duo/handoff-templates/builder-planner-chat.ts
100786
+ var init_builder_planner_chat = __esm(() => {
100787
+ init_builder_planner_code();
100788
+ });
100789
+
100698
100790
  // ../../services/backend/prompts/teams/duo/handoff-templates/builder.ts
100699
100791
  var duoBuilderHandoffContract;
100700
100792
  var init_builder = __esm(() => {
100701
- init_builder_to_planner();
100793
+ init_builder_planner_chat();
100794
+ init_builder_planner_code();
100795
+ init_contracts();
100702
100796
  duoBuilderHandoffContract = {
100703
100797
  role: "builder",
100704
100798
  receivesFrom: ["planner"],
100705
100799
  returnsTo: ["planner"],
100706
100800
  outboundTemplates: {
100707
- planner: (query) => getBuilderToPlannerHandoffTemplate({
100708
- chatroomId: query.chatroomId,
100709
- role: query.role,
100710
- cliEnvPrefix: query.cliEnvPrefix
100801
+ planner: handoffTemplateByMode({
100802
+ chat: getBuilderPlannerCodeTemplate,
100803
+ code: getBuilderPlannerCodeTemplate
100711
100804
  })
100712
100805
  }
100713
100806
  };
100714
100807
  });
100715
100808
 
100716
- // ../../services/backend/prompts/teams/duo/handoff-templates/planner-to-builder.ts
100717
- function getPlannerToBuilderHandoffTemplate() {
100718
- return `${getHandoffRecipientVisibilityCallout("builder")}
100809
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-architect-code.ts
100810
+ function getPlannerArchitectCodeTemplate(query) {
100811
+ return getEntryPointToArchitectHandoffTemplate(query);
100812
+ }
100813
+ var init_planner_architect_code = __esm(() => {
100814
+ init_architect_handoff_templates();
100815
+ });
100816
+
100817
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-architect-chat.ts
100818
+ var init_planner_architect_chat = __esm(() => {
100819
+ init_planner_architect_code();
100820
+ });
100719
100821
 
100720
- ${getDelegationBriefIntro()}
100822
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-builder-code.ts
100823
+ function getPlannerBuilderCodeBody() {
100824
+ return `${getDelegationBriefIntro()}
100721
100825
 
100722
100826
  **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
100827
 
@@ -100727,7 +100831,9 @@ ${getDelegationBriefIntro()}
100727
100831
 
100728
100832
  **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
100833
 
100730
- \`\`\`markdown
100834
+ 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.
100835
+
100836
+ \`\`\`\`markdown
100731
100837
  ## Summary
100732
100838
  <brief context for this delegation slice — what problem it solves and where it fits in the larger task>
100733
100839
 
@@ -100784,14 +100890,311 @@ Cross-file types, interfaces, or patterns that apply beyond a single file. Omit
100784
100890
  - <e.g. "Do not add new abstractions", "Do not refactor unrelated files", "Do not change existing public APIs">
100785
100891
 
100786
100892
  ## Skills to activate
100787
- - <e.g. chatroom skill activate code-review --chatroom-id=<id> --role=builder>
100893
+ - e.g. \`chatroom skill activate code-review --chatroom-id=<id> --role=builder\`
100788
100894
 
100789
100895
  ## Out of scope
100790
100896
  - <files or areas the builder must NOT touch in this slice>
100791
100897
 
100792
- Keep one slice ≈ one focused review surface. Delegate slices incrementally — one at a time, not all at once.`;
100898
+ \`\`\`\``;
100899
+ }
100900
+ function getPlannerBuilderCodeTemplate(_query) {
100901
+ return getPlannerBuilderCodeBody();
100902
+ }
100903
+ var init_planner_builder_code = () => {};
100904
+
100905
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-builder-chat.ts
100906
+ var init_planner_builder_chat = __esm(() => {
100907
+ init_planner_builder_code();
100908
+ });
100909
+
100910
+ // ../../services/backend/prompts/teams/researcher-handoff-templates.ts
100911
+ function getEntryPointToResearcherHandoffTemplate(query) {
100912
+ const entryPoint = query.fromRole;
100913
+ 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.
100914
+
100915
+ ### When to research
100916
+
100917
+ Research before delegating when the slice introduces something not already grounded in this repository:
100918
+ - a new library, API, external service, platform behavior, or version-sensitive dependency;
100919
+ - an unfamiliar subsystem;
100920
+ - a change with several plausible designs;
100921
+ - any ambiguity the user has not resolved.
100922
+
100923
+ Skip research when the change is a small, well-understood edit in code you have already inspected.
100924
+
100925
+ After completing the research, the researcher must return the evidence-backed brief to \`${entryPoint}\` with the normal handoff command.
100926
+
100927
+ \`\`\`bash
100928
+ ${handoffCommand({
100929
+ chatroomId: "<chatroom-id>",
100930
+ role: entryPoint,
100931
+ nextRole: "researcher",
100932
+ cliEnvPrefix: ""
100933
+ })}
100934
+ \`\`\``;
100935
+ }
100936
+ function getResearcherToEntryPointHandoffTemplate(query) {
100937
+ const entryPoint = query.toRole;
100938
+ 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.
100939
+
100940
+ ## Summary
100941
+ <state the answer to the core question in two to four sentences and whether any decision remains open>
100942
+
100943
+ ## Research questions
100944
+ <list each question exactly as asked or as derived from the request, numbered>
100945
+
100946
+ ## Answers
100947
+ <one entry per question, each tagged \`confirmed\` (with evidence), \`inferred\` (with reasoning), or \`unknown\`>
100948
+
100949
+ ## Repository evidence
100950
+ <concrete repository paths and symbols with what each shows; quote the relevant lines briefly>
100951
+
100952
+ ## External sources
100953
+ <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>
100954
+
100955
+ ## Grounded facts for the plan
100956
+ <the facts the planner can rely on when decomposing and delegating, each tagged confirmed or inferred>
100957
+
100958
+ ## Remaining ambiguity
100959
+ <each open decision, who must decide it, and a recommended default; write exactly \`None observed.\` if none remain>
100960
+
100961
+ ## Risks and constraints
100962
+ <constraints from the repository or external platform, and risks the plan must account for>
100963
+
100964
+ ## Work completed
100965
+ <paths inspected, searches run, and sources opened, with the result of each>
100966
+
100967
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100968
+
100969
+ \`\`\`bash
100970
+ ${handoffCommand({
100971
+ chatroomId: "<chatroom-id>",
100972
+ role: "researcher",
100973
+ nextRole: entryPoint,
100974
+ cliEnvPrefix: ""
100975
+ })}
100976
+ \`\`\``;
100977
+ }
100978
+ var init_researcher_handoff_templates = __esm(() => {
100979
+ init_command2();
100980
+ });
100981
+
100982
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-researcher-code.ts
100983
+ function getPlannerResearcherCodeTemplate(query) {
100984
+ return getEntryPointToResearcherHandoffTemplate(query);
100985
+ }
100986
+ var init_planner_researcher_code = __esm(() => {
100987
+ init_researcher_handoff_templates();
100988
+ });
100989
+
100990
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-researcher-chat.ts
100991
+ var init_planner_researcher_chat = __esm(() => {
100992
+ init_planner_researcher_code();
100993
+ });
100994
+
100995
+ // ../../services/backend/prompts/teams/triage-handoff-templates.ts
100996
+ function getEntryPointToTriageHandoffTemplate(query) {
100997
+ const entryPoint = query.fromRole;
100998
+ 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.
100999
+
101000
+ After completing the investigation, triage must return the evidence-backed report to \`${entryPoint}\` with the normal handoff command.
101001
+
101002
+ \`\`\`bash
101003
+ ${handoffCommand({
101004
+ chatroomId: "<chatroom-id>",
101005
+ role: entryPoint,
101006
+ nextRole: "triage",
101007
+ cliEnvPrefix: ""
101008
+ })}
101009
+ \`\`\``;
101010
+ }
101011
+ function getTriageToEntryPointHandoffTemplate(query) {
101012
+ const entryPoint = query.toRole;
101013
+ 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.
101014
+
101015
+ ## Summary
101016
+ <briefly state the diagnosis and whether the root cause was confirmed or remains a hypothesis>
101017
+
101018
+ ## Reported behavior
101019
+ <state the reported symptoms and expected behavior, including reproduction details and constraints recovered from the request or relevant history>
101020
+
101021
+ ## Root cause
101022
+ <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>
101023
+
101024
+ ## Reproduction attempt
101025
+ <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>
101026
+
101027
+ ## Proposed immediate fix
101028
+ <recommend the smallest appropriate change, naming the likely files and the specific change; do not implement it>
101029
+
101030
+ ## Systemic issues
101031
+ <list each separate systemic concern with repository evidence, impact, and follow-up concern, or write exactly: None observed.>
101032
+
101033
+ ## Work completed
101034
+ <state the code paths inspected and every test or reproduction action taken, including results>
101035
+
101036
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
101037
+
101038
+ \`\`\`bash
101039
+ ${handoffCommand({
101040
+ chatroomId: "<chatroom-id>",
101041
+ role: "triage",
101042
+ nextRole: entryPoint,
101043
+ cliEnvPrefix: ""
101044
+ })}
101045
+ \`\`\``;
101046
+ }
101047
+ var init_triage_handoff_templates = __esm(() => {
101048
+ init_command2();
101049
+ });
101050
+
101051
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-triage-code.ts
101052
+ function getPlannerTriageCodeTemplate(query) {
101053
+ return getEntryPointToTriageHandoffTemplate(query);
101054
+ }
101055
+ var init_planner_triage_code = __esm(() => {
101056
+ init_triage_handoff_templates();
101057
+ });
101058
+
101059
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-triage-chat.ts
101060
+ var init_planner_triage_chat = __esm(() => {
101061
+ init_planner_triage_code();
101062
+ });
101063
+
101064
+ // ../../services/backend/prompts/teams/uiux-engineer-handoff-templates.ts
101065
+ function getUiuxEngineerFocus() {
101066
+ return "complete user flows, loading/empty/error/success states, component ownership, theme tokens and layout, responsive details, and UI tests";
101067
+ }
101068
+ function getUiuxEngineerRequirements() {
101069
+ return `
101070
+ - Specify complete user flows with explicit loading, empty, error, success, disabled, and retry states where applicable.
101071
+ - Define component hierarchy and ownership, props/state/events, data boundaries, and interaction behavior.
101072
+ - Choose concrete existing ShadCN components with the Base UI backend and lucide-react/react-icons conventions; do not write "use an appropriate component."
101073
+ - Specify Tailwind utility classes or semantic theme-token classes for layout, spacing, sizing, typography, states, responsive behavior, and dark mode.
101074
+ - Provide the target HTML markup with exact class attributes and any required CSS/styles in the handoff.
101075
+ - Specify responsive breakpoints/layout behavior, visual feedback, destructive-action safeguards, exact files/components, and the UI/integration test plan.
101076
+ - Do not propose or require web accessibility implementation work unless the user explicitly requests it.`;
101077
+ }
101078
+ function getEntryPointToUiuxEngineerHandoffTemplate(query) {
101079
+ const entryPoint = query.fromRole;
101080
+ 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.
101081
+
101082
+ Provide the request, relevant constraints, and the files or product surfaces that need inspection. Ask for one evidence-backed design focused on ${getUiuxEngineerFocus()}.
101083
+
101084
+ 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.
101085
+
101086
+ \`\`\`bash
101087
+ ${handoffCommand({
101088
+ chatroomId: "<chatroom-id>",
101089
+ role: "uiux-engineer",
101090
+ nextRole: entryPoint,
101091
+ cliEnvPrefix: ""
101092
+ })}
101093
+ \`\`\``;
100793
101094
  }
100794
- var init_planner_to_builder = () => {};
101095
+ function getUiuxEngineerToEntryPointHandoffTemplate(query) {
101096
+ const entryPoint = query.toRole;
101097
+ const sharedContractsHeading = `## Shared contracts (${entryPoint}-owned)`;
101098
+ 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.
101099
+
101100
+ ## Summary
101101
+ <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>
101102
+
101103
+ ## Goal
101104
+ <state the one-sentence outcome this design delivers>
101105
+
101106
+ ## Key Knowledge for High Quality Bar
101107
+ <cite the inspected repository patterns and complete the UI/UX engineer checklist below; do not provide a high-level essay>
101108
+ - Produce exactly one recommended design for ${getUiuxEngineerFocus()}.
101109
+ - Name concrete repository paths, existing components/tokens, props/state/events, data boundaries, acceptance criteria, risks, and verification steps.
101110
+ ${getUiuxEngineerRequirements()}
101111
+
101112
+ ## Force Multipliers
101113
+ <name the existing components, patterns, tokens, utilities, and platform conventions to reuse, and state why each reduces implementation risk or duplication>
101114
+ - Keep the design within the repository's established source-of-truth boundaries and avoid introducing a new registry or abstraction without evidence.
101115
+
101116
+ ## Files to implement (exhaustive, file-level)
101117
+ 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.
101118
+ ${getFileReferenceGuidanceComment()}
101119
+
101120
+ ### \`<repo-relative/path.ext>\` (Required)
101121
+ **Change:** <precise add/modify/remove responsibility and why>
101122
+
101123
+ \`\`\`text
101124
+ // Target HTML markup, exact class attributes, and required CSS/styles.
101125
+ // Include component hierarchy and props/state/events needed for implementation.
101126
+ \`\`\`
101127
+
101128
+ <add one block per file; do not collapse multiple files into a directory or vague layer>
101129
+
101130
+ ${sharedContractsHeading}
101131
+ <list cross-file interfaces, component/data contracts, state boundaries, or write exactly \`Not Applicable.\` when genuinely inapplicable>
101132
+
101133
+ ### Interfaces & types
101134
+ \`\`\`typescript
101135
+ // Shared props, state, events, query shapes, or interaction contracts.
101136
+ \`\`\`
101137
+
101138
+ ### Reference snippets
101139
+ \`\`\`tsx
101140
+ // Canonical component imports, hook usage, or layout examples.
101141
+ \`\`\`
101142
+
101143
+ ## Requirements (acceptance criteria)
101144
+ - <one concrete, verifiable requirement per bullet; include exact states, interactions, classes/tokens, and responsive behavior>
101145
+ - Include UI and integration test coverage for the design's risk areas.
101146
+ - Verify the implemented user-facing feature end-to-end; unit tests alone are insufficient.
101147
+
101148
+ ## What to avoid
101149
+ - Do not implement code or edit files as the UI/UX engineer; this handoff is advisory only.
101150
+ - Do not present alternative designs, generic advice, or requirements without concrete evidence and file-level consequences.
101151
+ - Do not invent components, props, tokens, interaction behavior, or source-of-truth locations when existing repository patterns apply.
101152
+ - <explicit task-specific anti-patterns, scope boundaries, and destructive-action/source-of-truth pitfalls>
101153
+
101154
+ ## Skills to activate
101155
+ - <relevant repository skills and why they apply, or write exactly \`Not Applicable.\` when none apply>
101156
+
101157
+ ## Out of scope
101158
+ - <explicit files, flows, behavior, or migration work the implementer must not touch>
101159
+
101160
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
101161
+
101162
+ \`\`\`bash
101163
+ ${handoffCommand({
101164
+ chatroomId: "<chatroom-id>",
101165
+ role: "uiux-engineer",
101166
+ nextRole: entryPoint,
101167
+ cliEnvPrefix: ""
101168
+ })}
101169
+ \`\`\``;
101170
+ }
101171
+ var init_uiux_engineer_handoff_templates = __esm(() => {
101172
+ init_command2();
101173
+ });
101174
+
101175
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-uiux-engineer-code.ts
101176
+ function getPlannerUiuxEngineerCodeTemplate(query) {
101177
+ return getEntryPointToUiuxEngineerHandoffTemplate(query);
101178
+ }
101179
+ var init_planner_uiux_engineer_code = __esm(() => {
101180
+ init_uiux_engineer_handoff_templates();
101181
+ });
101182
+
101183
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-uiux-engineer-chat.ts
101184
+ var init_planner_uiux_engineer_chat = __esm(() => {
101185
+ init_planner_uiux_engineer_code();
101186
+ });
101187
+
101188
+ // ../../services/backend/prompts/utils/chat-handoff-template.ts
101189
+ function getChatToUserHandoffTemplate() {
101190
+ return `Instructions (not part of the message): chat response —
101191
+ \`\`\`markdown
101192
+ <write only the concise response the user should see; do not add handoff XML sections, proofs, context evidence, or placeholder text>
101193
+ \`\`\``;
101194
+ }
101195
+
101196
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-user-chat.ts
101197
+ var init_planner_user_chat = () => {};
100795
101198
 
100796
101199
  // ../../services/backend/prompts/utils/context-disclosure.ts
100797
101200
  function getContextReadDisclosureComment(params = {}) {
@@ -100814,16 +101217,9 @@ function getHandoffSeverityGuidanceBlock() {
100814
101217
  }
100815
101218
 
100816
101219
  // ../../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}\`.
101220
+ function getEntryPointToVerifierHandoffTemplate(query) {
101221
+ const entryPoint = query.fromRole;
101222
+ 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
101223
 
100828
101224
  ## Round
100829
101225
  <1 or 2; for 2, cite the round-1 verdict message id>
@@ -100849,8 +101245,7 @@ The verifier judges, from chatroom logs only, whether the user's last message wa
100849
101245
  ## Known gaps
100850
101246
  <anything incomplete, or exactly \`None.\`>
100851
101247
 
100852
- ## Handoff
100853
- Send this request to the verifier with the command below, then stop. The verdict returns to \`${entryPoint}\`.
101248
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100854
101249
 
100855
101250
  \`\`\`bash
100856
101251
  ${handoffCommand({
@@ -100861,13 +101256,9 @@ ${handoffCommand({
100861
101256
  })}
100862
101257
  \`\`\``;
100863
101258
  }
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.
101259
+ function getVerifierToEntryPointHandoffTemplate(query) {
101260
+ const entryPoint = query.toRole;
101261
+ 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
101262
 
100872
101263
  ## Verdict
100873
101264
  <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 +101281,7 @@ Return one advisory verdict for the authoritative request. This review is non-bi
100890
101281
  ## Scope and limits
100891
101282
  <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
101283
 
100893
- ## Handoff
100894
- Run the normal handoff command to \`${entryPoint}\` with this complete verdict, then stop.
101284
+ Instructions after the body (not part of the message): run the normal handoff command to \`${entryPoint}\` with the complete body above, then stop.
100895
101285
 
100896
101286
  \`\`\`bash
100897
101287
  ${handoffCommand({
@@ -101067,195 +101457,49 @@ var init_handoff_report_template_body = __esm(() => {
101067
101457
  init_unresolved_decisions();
101068
101458
  });
101069
101459
 
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)")}
101460
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-user-code.ts
101461
+ function getPlannerUserCodeTemplate(roleGuidanceContext) {
101462
+ return `${getHandoffReportTemplateIntro()}
101075
101463
 
101076
101464
  \`\`\`markdown
101077
101465
  ${getHandoffReportTemplateBody(roleGuidanceContext, { includeProofOfVerification: true })}
101078
101466
  \`\`\``;
101079
101467
  }
101080
- var init_planner_to_user = __esm(() => {
101468
+ var init_planner_user_code = __esm(() => {
101081
101469
  init_handoff_report_template_body();
101082
101470
  });
101083
101471
 
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
- \`\`\``;
101128
- }
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
- \`\`\``;
101472
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-verifier-code.ts
101473
+ function getPlannerVerifierCodeTemplate(query) {
101474
+ return getEntryPointToVerifierHandoffTemplate(query);
101175
101475
  }
101176
- var init_researcher_handoff_templates = __esm(() => {
101177
- init_command2();
101476
+ var init_planner_verifier_code = __esm(() => {
101477
+ init_verifier_handoff_templates();
101178
101478
  });
101179
101479
 
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();
101480
+ // ../../services/backend/prompts/teams/duo/handoff-templates/planner-verifier-chat.ts
101481
+ var init_planner_verifier_chat = __esm(() => {
101482
+ init_planner_verifier_code();
101246
101483
  });
101247
101484
 
101248
101485
  // ../../services/backend/prompts/teams/duo/handoff-templates/planner.ts
101249
101486
  var duoPlannerHandoffContract;
101250
101487
  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();
101488
+ init_planner_architect_chat();
101489
+ init_planner_architect_code();
101490
+ init_planner_builder_chat();
101491
+ init_planner_builder_code();
101492
+ init_planner_researcher_chat();
101493
+ init_planner_researcher_code();
101494
+ init_planner_triage_chat();
101495
+ init_planner_triage_code();
101496
+ init_planner_uiux_engineer_chat();
101497
+ init_planner_uiux_engineer_code();
101498
+ init_planner_user_chat();
101499
+ init_planner_user_code();
101500
+ init_planner_verifier_chat();
101501
+ init_planner_verifier_code();
101502
+ init_contracts();
101259
101503
  duoPlannerHandoffContract = {
101260
101504
  role: "planner",
101261
101505
  receivesFrom: [
@@ -101267,215 +101511,172 @@ var init_planner = __esm(() => {
101267
101511
  "researcher",
101268
101512
  "verifier"
101269
101513
  ],
101270
- returnsTo: ["builder", "architect", "uiux-engineer", "triage", "researcher", "verifier", "user"],
101514
+ returnsTo: ["user", "builder", "architect", "uiux-engineer", "triage", "researcher", "verifier"],
101271
101515
  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
101516
+ builder: handoffTemplateByMode({
101517
+ chat: getPlannerBuilderCodeTemplate,
101518
+ code: getPlannerBuilderCodeTemplate
101519
+ }),
101520
+ architect: handoffTemplateByMode({
101521
+ chat: getPlannerArchitectCodeTemplate,
101522
+ code: getPlannerArchitectCodeTemplate
101523
+ }),
101524
+ "uiux-engineer": handoffTemplateByMode({
101525
+ chat: getPlannerUiuxEngineerCodeTemplate,
101526
+ code: getPlannerUiuxEngineerCodeTemplate
101527
+ }),
101528
+ triage: handoffTemplateByMode({
101529
+ chat: getPlannerTriageCodeTemplate,
101530
+ code: getPlannerTriageCodeTemplate
101531
+ }),
101532
+ researcher: handoffTemplateByMode({
101533
+ chat: getPlannerResearcherCodeTemplate,
101534
+ code: getPlannerResearcherCodeTemplate
101535
+ }),
101536
+ verifier: handoffTemplateByMode({
101537
+ chat: getPlannerVerifierCodeTemplate,
101538
+ code: getPlannerVerifierCodeTemplate
101539
+ }),
101540
+ user: handoffTemplateByMode({
101541
+ chat: getChatToUserHandoffTemplate,
101542
+ code: getPlannerUserCodeTemplate
101282
101543
  })
101283
101544
  }
101284
101545
  };
101285
101546
  });
101286
101547
 
101548
+ // ../../services/backend/prompts/teams/duo/handoff-templates/researcher-planner-code.ts
101549
+ function getResearcherPlannerCodeTemplate(query) {
101550
+ return getResearcherToEntryPointHandoffTemplate(query);
101551
+ }
101552
+ var init_researcher_planner_code = __esm(() => {
101553
+ init_researcher_handoff_templates();
101554
+ });
101555
+
101556
+ // ../../services/backend/prompts/teams/duo/handoff-templates/researcher-planner-chat.ts
101557
+ var init_researcher_planner_chat = __esm(() => {
101558
+ init_researcher_planner_code();
101559
+ });
101560
+
101287
101561
  // ../../services/backend/prompts/teams/duo/handoff-templates/researcher.ts
101288
101562
  var duoResearcherHandoffContract;
101289
101563
  var init_researcher = __esm(() => {
101290
- init_researcher_handoff_templates();
101564
+ init_researcher_planner_chat();
101565
+ init_researcher_planner_code();
101566
+ init_contracts();
101291
101567
  duoResearcherHandoffContract = {
101292
101568
  role: "researcher",
101293
101569
  receivesFrom: ["planner"],
101294
101570
  returnsTo: ["planner"],
101295
101571
  outboundTemplates: {
101296
- planner: () => getResearcherToEntryPointHandoffTemplate("planner")
101572
+ planner: handoffTemplateByMode({
101573
+ chat: getResearcherPlannerCodeTemplate,
101574
+ code: getResearcherPlannerCodeTemplate
101575
+ })
101297
101576
  }
101298
101577
  };
101299
101578
  });
101300
101579
 
101580
+ // ../../services/backend/prompts/teams/duo/handoff-templates/triage-planner-code.ts
101581
+ function getTriagePlannerCodeTemplate(query) {
101582
+ return getTriageToEntryPointHandoffTemplate(query);
101583
+ }
101584
+ var init_triage_planner_code = __esm(() => {
101585
+ init_triage_handoff_templates();
101586
+ });
101587
+
101588
+ // ../../services/backend/prompts/teams/duo/handoff-templates/triage-planner-chat.ts
101589
+ var init_triage_planner_chat = __esm(() => {
101590
+ init_triage_planner_code();
101591
+ });
101592
+
101301
101593
  // ../../services/backend/prompts/teams/duo/handoff-templates/triage.ts
101302
101594
  var duoTriageHandoffContract;
101303
101595
  var init_triage = __esm(() => {
101304
- init_triage_handoff_templates();
101596
+ init_triage_planner_chat();
101597
+ init_triage_planner_code();
101598
+ init_contracts();
101305
101599
  duoTriageHandoffContract = {
101306
101600
  role: "triage",
101307
101601
  receivesFrom: ["planner"],
101308
101602
  returnsTo: ["planner"],
101309
101603
  outboundTemplates: {
101310
- planner: () => getTriageToEntryPointHandoffTemplate("planner")
101604
+ planner: handoffTemplateByMode({
101605
+ chat: getTriagePlannerCodeTemplate,
101606
+ code: getTriagePlannerCodeTemplate
101607
+ })
101311
101608
  }
101312
101609
  };
101313
101610
  });
101314
101611
 
101612
+ // ../../services/backend/prompts/teams/duo/handoff-templates/uiux-engineer-planner-code.ts
101613
+ function getUiuxEngineerPlannerCodeTemplate(query) {
101614
+ return getUiuxEngineerToEntryPointHandoffTemplate(query);
101615
+ }
101616
+ var init_uiux_engineer_planner_code = __esm(() => {
101617
+ init_uiux_engineer_handoff_templates();
101618
+ });
101619
+
101620
+ // ../../services/backend/prompts/teams/duo/handoff-templates/uiux-engineer-planner-chat.ts
101621
+ var init_uiux_engineer_planner_chat = __esm(() => {
101622
+ init_uiux_engineer_planner_code();
101623
+ });
101624
+
101315
101625
  // ../../services/backend/prompts/teams/duo/handoff-templates/uiux-engineer.ts
101316
101626
  var duoUiuxEngineerHandoffContract;
101317
101627
  var init_uiux_engineer = __esm(() => {
101318
- init_uiux_engineer_handoff_templates();
101628
+ init_uiux_engineer_planner_chat();
101629
+ init_uiux_engineer_planner_code();
101630
+ init_contracts();
101319
101631
  duoUiuxEngineerHandoffContract = {
101320
101632
  role: "uiux-engineer",
101321
101633
  receivesFrom: ["planner"],
101322
101634
  returnsTo: ["planner"],
101323
101635
  outboundTemplates: {
101324
- planner: () => getUiuxEngineerToEntryPointHandoffTemplate("planner")
101636
+ planner: handoffTemplateByMode({
101637
+ chat: getUiuxEngineerPlannerCodeTemplate,
101638
+ code: getUiuxEngineerPlannerCodeTemplate
101639
+ })
101325
101640
  }
101326
101641
  };
101327
101642
  });
101328
101643
 
101644
+ // ../../services/backend/prompts/teams/duo/handoff-templates/verifier-planner-code.ts
101645
+ function getVerifierPlannerCodeTemplate(query) {
101646
+ return getVerifierToEntryPointHandoffTemplate(query);
101647
+ }
101648
+ var init_verifier_planner_code = __esm(() => {
101649
+ init_verifier_handoff_templates();
101650
+ });
101651
+
101652
+ // ../../services/backend/prompts/teams/duo/handoff-templates/verifier-planner-chat.ts
101653
+ var init_verifier_planner_chat = __esm(() => {
101654
+ init_verifier_planner_code();
101655
+ });
101656
+
101329
101657
  // ../../services/backend/prompts/teams/duo/handoff-templates/verifier.ts
101330
101658
  var duoVerifierHandoffContract;
101331
101659
  var init_verifier = __esm(() => {
101332
- init_verifier_handoff_templates();
101660
+ init_verifier_planner_chat();
101661
+ init_verifier_planner_code();
101662
+ init_contracts();
101333
101663
  duoVerifierHandoffContract = {
101334
101664
  role: "verifier",
101335
101665
  receivesFrom: ["planner"],
101336
101666
  returnsTo: ["planner"],
101337
101667
  outboundTemplates: {
101338
- planner: () => getVerifierToEntryPointHandoffTemplate("planner")
101668
+ planner: handoffTemplateByMode({
101669
+ chat: getVerifierPlannerCodeTemplate,
101670
+ code: getVerifierPlannerCodeTemplate
101671
+ })
101339
101672
  }
101340
101673
  };
101341
101674
  });
101342
101675
 
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
101676
  // ../../services/backend/prompts/teams/duo/handoff-templates/index.ts
101469
101677
  function listDuoRoleHandoffContracts() {
101470
101678
  return validatedDuoRoleHandoffContracts;
101471
101679
  }
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
101680
  var DUO_ROLE_HANDOFF_CATALOG, DUO_ROLE_HANDOFF_CONTRACTS, validatedDuoRoleHandoffContracts;
101480
101681
  var init_handoff_templates = __esm(() => {
101481
101682
  init_architect();
@@ -101502,99 +101703,240 @@ var init_handoff_templates = __esm(() => {
101502
101703
  })();
101503
101704
  });
101504
101705
 
101706
+ // ../../services/backend/prompts/teams/solo/handoff-templates/architect-solo-code.ts
101707
+ function getArchitectSoloCodeTemplate(query) {
101708
+ return getArchitectToEntryPointHandoffTemplate(query);
101709
+ }
101710
+ var init_architect_solo_code = __esm(() => {
101711
+ init_architect_handoff_templates();
101712
+ });
101713
+
101714
+ // ../../services/backend/prompts/teams/solo/handoff-templates/architect-solo-chat.ts
101715
+ var init_architect_solo_chat = __esm(() => {
101716
+ init_architect_solo_code();
101717
+ });
101718
+
101505
101719
  // ../../services/backend/prompts/teams/solo/handoff-templates/architect.ts
101506
101720
  var soloArchitectHandoffContract;
101507
101721
  var init_architect2 = __esm(() => {
101508
- init_architect_handoff_templates();
101722
+ init_architect_solo_chat();
101723
+ init_architect_solo_code();
101724
+ init_contracts();
101509
101725
  soloArchitectHandoffContract = {
101510
101726
  role: "architect",
101511
101727
  receivesFrom: ["solo"],
101512
101728
  returnsTo: ["solo"],
101513
101729
  outboundTemplates: {
101514
- solo: () => getArchitectToEntryPointHandoffTemplate("solo")
101730
+ solo: handoffTemplateByMode({
101731
+ chat: getArchitectSoloCodeTemplate,
101732
+ code: getArchitectSoloCodeTemplate
101733
+ })
101515
101734
  }
101516
101735
  };
101517
101736
  });
101518
101737
 
101519
- // ../../services/backend/prompts/teams/solo/handoff-templates/solo-to-user.ts
101520
- function getSoloToUserReportTemplate(roleGuidanceContext) {
101521
- return `${getHandoffRecipientVisibilityCallout("user")}
101738
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-architect-code.ts
101739
+ function getSoloArchitectCodeTemplate(query) {
101740
+ return getEntryPointToArchitectHandoffTemplate(query);
101741
+ }
101742
+ var init_solo_architect_code = __esm(() => {
101743
+ init_architect_handoff_templates();
101744
+ });
101745
+
101746
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-architect-chat.ts
101747
+ var init_solo_architect_chat = __esm(() => {
101748
+ init_solo_architect_code();
101749
+ });
101750
+
101751
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-triage-code.ts
101752
+ function getSoloTriageCodeTemplate(query) {
101753
+ return getEntryPointToTriageHandoffTemplate(query);
101754
+ }
101755
+ var init_solo_triage_code = __esm(() => {
101756
+ init_triage_handoff_templates();
101757
+ });
101758
+
101759
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-triage-chat.ts
101760
+ var init_solo_triage_chat = __esm(() => {
101761
+ init_solo_triage_code();
101762
+ });
101763
+
101764
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-uiux-engineer-code.ts
101765
+ function getSoloUiuxEngineerCodeTemplate(query) {
101766
+ return getEntryPointToUiuxEngineerHandoffTemplate(query);
101767
+ }
101768
+ var init_solo_uiux_engineer_code = __esm(() => {
101769
+ init_uiux_engineer_handoff_templates();
101770
+ });
101771
+
101772
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-uiux-engineer-chat.ts
101773
+ var init_solo_uiux_engineer_chat = __esm(() => {
101774
+ init_solo_uiux_engineer_code();
101775
+ });
101522
101776
 
101523
- ${getHandoffReportTemplateIntro("Report Template (Solo → User)")}
101777
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-user-chat.ts
101778
+ var init_solo_user_chat = () => {};
101779
+
101780
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-user-code.ts
101781
+ function getSoloUserCodeTemplate(roleGuidanceContext) {
101782
+ return `${getHandoffReportTemplateIntro()}
101524
101783
 
101525
101784
  \`\`\`markdown
101526
101785
  ${getHandoffReportTemplateBody(roleGuidanceContext, { includeProofOfVerification: true })}
101527
101786
  \`\`\``;
101528
101787
  }
101529
- var init_solo_to_user = __esm(() => {
101788
+ var init_solo_user_code = __esm(() => {
101530
101789
  init_handoff_report_template_body();
101531
101790
  });
101532
101791
 
101792
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-verifier-code.ts
101793
+ function getSoloVerifierCodeTemplate(query) {
101794
+ return getEntryPointToVerifierHandoffTemplate(query);
101795
+ }
101796
+ var init_solo_verifier_code = __esm(() => {
101797
+ init_verifier_handoff_templates();
101798
+ });
101799
+
101800
+ // ../../services/backend/prompts/teams/solo/handoff-templates/solo-verifier-chat.ts
101801
+ var init_solo_verifier_chat = __esm(() => {
101802
+ init_solo_verifier_code();
101803
+ });
101804
+
101533
101805
  // ../../services/backend/prompts/teams/solo/handoff-templates/solo.ts
101534
101806
  var soloHandoffContract;
101535
101807
  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();
101808
+ init_solo_architect_chat();
101809
+ init_solo_architect_code();
101810
+ init_solo_triage_chat();
101811
+ init_solo_triage_code();
101812
+ init_solo_uiux_engineer_chat();
101813
+ init_solo_uiux_engineer_code();
101814
+ init_solo_user_chat();
101815
+ init_solo_user_code();
101816
+ init_solo_verifier_chat();
101817
+ init_solo_verifier_code();
101818
+ init_contracts();
101542
101819
  soloHandoffContract = {
101543
101820
  role: "solo",
101544
101821
  receivesFrom: ["user", "architect", "uiux-engineer", "triage", "verifier"],
101545
- returnsTo: ["architect", "uiux-engineer", "triage", "verifier", "user"],
101822
+ returnsTo: ["user", "architect", "uiux-engineer", "triage", "verifier"],
101546
101823
  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
101824
+ architect: handoffTemplateByMode({
101825
+ chat: getSoloArchitectCodeTemplate,
101826
+ code: getSoloArchitectCodeTemplate
101827
+ }),
101828
+ "uiux-engineer": handoffTemplateByMode({
101829
+ chat: getSoloUiuxEngineerCodeTemplate,
101830
+ code: getSoloUiuxEngineerCodeTemplate
101831
+ }),
101832
+ triage: handoffTemplateByMode({
101833
+ chat: getSoloTriageCodeTemplate,
101834
+ code: getSoloTriageCodeTemplate
101835
+ }),
101836
+ verifier: handoffTemplateByMode({
101837
+ chat: getSoloVerifierCodeTemplate,
101838
+ code: getSoloVerifierCodeTemplate
101839
+ }),
101840
+ user: handoffTemplateByMode({
101841
+ chat: getChatToUserHandoffTemplate,
101842
+ code: getSoloUserCodeTemplate
101555
101843
  })
101556
101844
  }
101557
101845
  };
101558
101846
  });
101559
101847
 
101848
+ // ../../services/backend/prompts/teams/solo/handoff-templates/triage-solo-code.ts
101849
+ function getTriageSoloCodeTemplate(query) {
101850
+ return getTriageToEntryPointHandoffTemplate(query);
101851
+ }
101852
+ var init_triage_solo_code = __esm(() => {
101853
+ init_triage_handoff_templates();
101854
+ });
101855
+
101856
+ // ../../services/backend/prompts/teams/solo/handoff-templates/triage-solo-chat.ts
101857
+ var init_triage_solo_chat = __esm(() => {
101858
+ init_triage_solo_code();
101859
+ });
101860
+
101560
101861
  // ../../services/backend/prompts/teams/solo/handoff-templates/triage.ts
101561
101862
  var soloTriageHandoffContract;
101562
101863
  var init_triage2 = __esm(() => {
101563
- init_triage_handoff_templates();
101864
+ init_triage_solo_chat();
101865
+ init_triage_solo_code();
101866
+ init_contracts();
101564
101867
  soloTriageHandoffContract = {
101565
101868
  role: "triage",
101566
101869
  receivesFrom: ["solo"],
101567
101870
  returnsTo: ["solo"],
101568
101871
  outboundTemplates: {
101569
- solo: () => getTriageToEntryPointHandoffTemplate("solo")
101872
+ solo: handoffTemplateByMode({
101873
+ chat: getTriageSoloCodeTemplate,
101874
+ code: getTriageSoloCodeTemplate
101875
+ })
101570
101876
  }
101571
101877
  };
101572
101878
  });
101573
101879
 
101880
+ // ../../services/backend/prompts/teams/solo/handoff-templates/uiux-engineer-solo-code.ts
101881
+ function getUiuxEngineerSoloCodeTemplate(query) {
101882
+ return getUiuxEngineerToEntryPointHandoffTemplate(query);
101883
+ }
101884
+ var init_uiux_engineer_solo_code = __esm(() => {
101885
+ init_uiux_engineer_handoff_templates();
101886
+ });
101887
+
101888
+ // ../../services/backend/prompts/teams/solo/handoff-templates/uiux-engineer-solo-chat.ts
101889
+ var init_uiux_engineer_solo_chat = __esm(() => {
101890
+ init_uiux_engineer_solo_code();
101891
+ });
101892
+
101574
101893
  // ../../services/backend/prompts/teams/solo/handoff-templates/uiux-engineer.ts
101575
101894
  var soloUiuxEngineerHandoffContract;
101576
101895
  var init_uiux_engineer2 = __esm(() => {
101577
- init_uiux_engineer_handoff_templates();
101896
+ init_uiux_engineer_solo_chat();
101897
+ init_uiux_engineer_solo_code();
101898
+ init_contracts();
101578
101899
  soloUiuxEngineerHandoffContract = {
101579
101900
  role: "uiux-engineer",
101580
101901
  receivesFrom: ["solo"],
101581
101902
  returnsTo: ["solo"],
101582
101903
  outboundTemplates: {
101583
- solo: () => getUiuxEngineerToEntryPointHandoffTemplate("solo")
101904
+ solo: handoffTemplateByMode({
101905
+ chat: getUiuxEngineerSoloCodeTemplate,
101906
+ code: getUiuxEngineerSoloCodeTemplate
101907
+ })
101584
101908
  }
101585
101909
  };
101586
101910
  });
101587
101911
 
101912
+ // ../../services/backend/prompts/teams/solo/handoff-templates/verifier-solo-code.ts
101913
+ function getVerifierSoloCodeTemplate(query) {
101914
+ return getVerifierToEntryPointHandoffTemplate(query);
101915
+ }
101916
+ var init_verifier_solo_code = __esm(() => {
101917
+ init_verifier_handoff_templates();
101918
+ });
101919
+
101920
+ // ../../services/backend/prompts/teams/solo/handoff-templates/verifier-solo-chat.ts
101921
+ var init_verifier_solo_chat = __esm(() => {
101922
+ init_verifier_solo_code();
101923
+ });
101924
+
101588
101925
  // ../../services/backend/prompts/teams/solo/handoff-templates/verifier.ts
101589
101926
  var soloVerifierHandoffContract;
101590
101927
  var init_verifier2 = __esm(() => {
101591
- init_verifier_handoff_templates();
101928
+ init_verifier_solo_chat();
101929
+ init_verifier_solo_code();
101930
+ init_contracts();
101592
101931
  soloVerifierHandoffContract = {
101593
101932
  role: "verifier",
101594
101933
  receivesFrom: ["solo"],
101595
101934
  returnsTo: ["solo"],
101596
101935
  outboundTemplates: {
101597
- solo: () => getVerifierToEntryPointHandoffTemplate("solo")
101936
+ solo: handoffTemplateByMode({
101937
+ chat: getVerifierSoloCodeTemplate,
101938
+ code: getVerifierSoloCodeTemplate
101939
+ })
101598
101940
  }
101599
101941
  };
101600
101942
  });
@@ -101603,13 +101945,6 @@ var init_verifier2 = __esm(() => {
101603
101945
  function listSoloRoleHandoffContracts() {
101604
101946
  return validatedSoloRoleHandoffContracts;
101605
101947
  }
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
101948
  var SOLO_ROLE_HANDOFF_CATALOG, SOLO_ROLE_HANDOFF_CONTRACTS, validatedSoloRoleHandoffContracts;
101614
101949
  var init_handoff_templates2 = __esm(() => {
101615
101950
  init_architect2();
@@ -101633,85 +101968,117 @@ var init_handoff_templates2 = __esm(() => {
101633
101968
  });
101634
101969
 
101635
101970
  // ../../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;
101971
+ function listHandoffTemplatePairs(teamId, fromRole) {
101972
+ const team = (teamId ?? DEFAULT_HANDOFF_TEAM_ID).trim().toLowerCase();
101973
+ if (!isTeamPresetId(team))
101974
+ return [];
101975
+ const normalizedFrom = fromRole === undefined ? undefined : fromRole.trim().toLowerCase();
101976
+ const contracts = normalizedFrom === undefined ? BUILTIN_TEAM_HANDOFF_CONTRACTS[team] : BUILTIN_TEAM_HANDOFF_CONTRACTS[team].filter((contract) => contract.role.toLowerCase() === normalizedFrom);
101977
+ return contracts.flatMap((contract) => contract.returnsTo.map((toRole) => ({
101978
+ teamId: team,
101979
+ fromRole: contract.role,
101980
+ toRole
101981
+ })));
101982
+ }
101983
+ function resolveHandoffTemplatePair(input, command) {
101984
+ const from = normalizeHandoffRole(input.from);
101985
+ const to = normalizeHandoffRole(input.to);
101986
+ const legacyRole = normalizeHandoffRole(input.legacyRole);
101987
+ const legacyNextRole = normalizeHandoffRole(input.legacyNextRole);
101988
+ const team = (input.teamId ?? DEFAULT_HANDOFF_TEAM_ID).trim().toLowerCase();
101989
+ if (from !== undefined && to !== undefined) {
101990
+ if (!isTeamPresetId(team)) {
101991
+ throw new HandoffTemplatePairError("UNKNOWN_TEAM", unknownTeamMessage(team));
101992
+ }
101993
+ const contracts = BUILTIN_TEAM_HANDOFF_CONTRACTS[team];
101994
+ const contract = contracts.find((candidate) => candidate.role.toLowerCase() === from);
101995
+ if (!contract) {
101996
+ throw new HandoffTemplatePairError("UNKNOWN_FROM_ROLE", unknownFromRoleMessage({ from, team, roles: contracts.map((c) => c.role) }));
101997
+ }
101998
+ if (!contract.returnsTo.includes(to)) {
101999
+ throw new HandoffTemplatePairError("UNKNOWN_PAIR", unknownPairMessage({ from, to, team, recipients: contract.returnsTo }));
102000
+ }
102001
+ return { teamId: team, fromRole: contract.role, toRole: to };
102002
+ }
102003
+ if (legacyRole !== undefined || legacyNextRole !== undefined) {
102004
+ throw new HandoffTemplatePairError("LEGACY_ROLE_FLAGS", legacyRoleFlagsMessage(command, {
102005
+ teamId: team,
102006
+ legacyRole,
102007
+ legacyNextRole,
102008
+ mode: normalizeHandoffMode(input.mode),
102009
+ rolePairs: legacyRole === undefined ? undefined : listHandoffTemplatePairs(team, legacyRole)
102010
+ }));
102011
+ }
102012
+ const missing = from === undefined && to === undefined ? "--from, --to" : from === undefined ? "--from" : "--to";
102013
+ throw new HandoffTemplatePairError("MISSING_PAIR", missingPairMessage(command, missing));
102014
+ }
102015
+ function resolveHandoffTemplateSelection(input, command) {
102016
+ const pair = resolveHandoffTemplatePair(input, command);
102017
+ const mode = normalizeHandoffMode(input.mode);
102018
+ if (mode === undefined) {
102019
+ throw new HandoffTemplatePairError("MISSING_MODE", missingModeMessage(command));
102020
+ }
102021
+ if (!isConversationMode2(mode)) {
102022
+ throw new HandoffTemplatePairError("UNKNOWN_MODE", unknownModeMessage(mode));
102023
+ }
102024
+ return { pair, mode };
101643
102025
  }
101644
- function listHandoffTemplates(query) {
101645
- const teamId = (query.teamId ?? "duo").toLowerCase();
101646
- const contracts = resolveTeamContracts(teamId);
101647
- if (!contracts)
102026
+ function renderHandoffTemplate(pair, options) {
102027
+ const contract = BUILTIN_TEAM_HANDOFF_CONTRACTS[pair.teamId].find((candidate) => candidate.role.toLowerCase() === pair.fromRole);
102028
+ const getter = contract?.outboundTemplates[pair.toRole];
102029
+ if (!getter)
101648
102030
  return null;
101649
- const contract = contracts.find((candidate) => candidate.role.toLowerCase() === query.role.toLowerCase());
101650
- if (!contract)
102031
+ const body = getter({
102032
+ ...options,
102033
+ teamId: pair.teamId,
102034
+ fromRole: pair.fromRole,
102035
+ toRole: pair.toRole,
102036
+ role: pair.fromRole
102037
+ });
102038
+ if (!body)
101651
102039
  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;
102040
+ return [
102041
+ getHandoffRecipientVisibilityCallout(pair.toRole),
102042
+ getHandoffTemplateTitleLine(pair),
102043
+ body
102044
+ ].join(`
102045
+
102046
+ `);
101684
102047
  }
102048
+ function getReplyHandoffTemplatePair(pair) {
102049
+ const contract = BUILTIN_TEAM_HANDOFF_CONTRACTS[pair.teamId].find((candidate) => candidate.role.toLowerCase() === pair.toRole);
102050
+ const getter = contract?.outboundTemplates[pair.fromRole];
102051
+ if (!getter)
102052
+ return null;
102053
+ return { teamId: pair.teamId, fromRole: pair.toRole, toRole: pair.fromRole };
102054
+ }
102055
+ var BUILTIN_TEAM_HANDOFF_CONTRACTS;
101685
102056
  var init_handoff_templates3 = __esm(() => {
102057
+ init_pair();
101686
102058
  init_handoff_templates();
101687
102059
  init_handoff_templates2();
102060
+ BUILTIN_TEAM_HANDOFF_CONTRACTS = {
102061
+ duo: listDuoRoleHandoffContracts(),
102062
+ solo: listSoloRoleHandoffContracts()
102063
+ };
101688
102064
  });
101689
102065
 
101690
102066
  // ../../services/backend/prompts/cli/handoff/view-template.ts
101691
102067
  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
102068
+ const { pair, mode } = resolveHandoffTemplateSelection(params, "view-template");
102069
+ const template = renderHandoffTemplate(pair, {
102070
+ nativeIntegration: params.nativeIntegration ?? true,
102071
+ cliEnvPrefix: params.cliEnvPrefix,
102072
+ conversationMode: mode
101705
102073
  });
101706
102074
  if (!template) {
101707
- throw new Error(`No handoff template for ${params.role} → ${params.nextRole}`);
102075
+ throw new HandoffTemplatePairError("UNKNOWN_PAIR", unrenderablePairMessage(pair));
101708
102076
  }
101709
102077
  return template;
101710
102078
  }
101711
102079
  var init_view_template2 = __esm(() => {
101712
- init_architect_handoff_templates();
101713
- init_uiux_engineer_handoff_templates();
101714
102080
  init_handoff_templates3();
102081
+ init_pair();
101715
102082
  });
101716
102083
 
101717
102084
  // src/commands/handoff/view-template.ts
@@ -101720,48 +102087,49 @@ __export(exports_view_template, {
101720
102087
  printHandoffViewTemplate: () => printHandoffViewTemplate
101721
102088
  });
101722
102089
  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);
102090
+ try {
102091
+ console.log(viewHandoffTemplate({ ...options, nativeIntegration: true }));
102092
+ } catch (err) {
102093
+ console.error(`❌ ${err.message}`);
102094
+ process.exit(1);
102095
+ }
101730
102096
  }
101731
102097
  var init_view_template3 = __esm(() => {
101732
102098
  init_view_template2();
101733
102099
  });
101734
102100
 
101735
102101
  // ../../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
102102
  function listHandoffTemplatesCommand(params) {
101752
- const listing = listHandoffTemplates({
101753
- role: params.role,
101754
- teamId: params.teamId,
101755
- cliEnvPrefix: params.cliEnvPrefix
102103
+ const { pair, mode } = resolveHandoffTemplateSelection(params, "list-templates");
102104
+ const reply = getReplyHandoffTemplatePair(pair);
102105
+ const template = renderHandoffTemplate(pair, {
102106
+ nativeIntegration: true,
102107
+ cliEnvPrefix: params.cliEnvPrefix,
102108
+ conversationMode: mode
101756
102109
  });
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.`);
102110
+ if (!template) {
102111
+ throw new HandoffTemplatePairError("UNKNOWN_PAIR", unrenderablePairMessage(pair));
101760
102112
  }
101761
- return formatHandoffTemplateListing(listing);
102113
+ const sendCommand = handoffCommand({
102114
+ chatroomId: "<chatroom-id>",
102115
+ role: pair.fromRole,
102116
+ nextRole: pair.toRole,
102117
+ cliEnvPrefix: params.cliEnvPrefix ?? ""
102118
+ }).split(`
102119
+ `)[0];
102120
+ return [
102121
+ `Handoff template ${formatHandoffPairLabel(pair)} (team: \`${pair.teamId}\`, mode: \`${mode}\`, key: \`${formatHandoffTemplateKey({ pair, mode })}\`)`,
102122
+ `Send with: ${sendCommand}`,
102123
+ reply ? `Reply pair: ${formatHandoffPairLabel(reply)} (view: ${formatHandoffTemplateCommand("view-template", reply, params.cliEnvPrefix, mode)})` : `Reply pair: none (\`${pair.toRole}\` replies free-form)`,
102124
+ "",
102125
+ template
102126
+ ].join(`
102127
+ `);
101762
102128
  }
101763
102129
  var init_list_templates = __esm(() => {
101764
102130
  init_handoff_templates3();
102131
+ init_pair();
102132
+ init_command2();
101765
102133
  });
101766
102134
 
101767
102135
  // src/commands/handoff/list-templates.ts
@@ -101771,12 +102139,7 @@ __export(exports_list_templates, {
101771
102139
  });
101772
102140
  function printHandoffListTemplates(options) {
101773
102141
  try {
101774
- const output = listHandoffTemplatesCommand({
101775
- role: options.role,
101776
- teamId: options.teamId,
101777
- cliEnvPrefix: options.cliEnvPrefix
101778
- });
101779
- console.log(output);
102142
+ console.log(listHandoffTemplatesCommand(options));
101780
102143
  } catch (err) {
101781
102144
  console.error(`❌ ${err.message}`);
101782
102145
  process.exit(1);
@@ -102071,8 +102434,17 @@ var init_commands_reference = __esm(() => {
102071
102434
  init_command4();
102072
102435
  init_utils3();
102073
102436
  });
102437
+
102438
+ // ../../services/backend/prompts/cli/sections/handoff-template-discovery.ts
102439
+ var init_handoff_template_discovery = __esm(() => {
102440
+ init_handoff_templates3();
102441
+ init_pair();
102442
+ });
102443
+
102074
102444
  // ../../services/backend/prompts/cli/sections/core-responsibilities.ts
102075
- var init_core_responsibilities = () => {};
102445
+ var init_core_responsibilities = __esm(() => {
102446
+ init_handoff_template_discovery();
102447
+ });
102076
102448
  // ../../services/backend/prompts/cli/sections/inter-role-handoff-rule.ts
102077
102449
  function getInterRoleHandoffRule() {
102078
102450
  return [
@@ -102095,6 +102467,7 @@ var init_operating_model = () => {};
102095
102467
  // ../../services/backend/prompts/cli/sections/index.ts
102096
102468
  var init_sections = __esm(() => {
102097
102469
  init_core_responsibilities();
102470
+ init_handoff_template_discovery();
102098
102471
  init_handoff_rules();
102099
102472
  init_proof_of_verification2();
102100
102473
  init_operating_model();
@@ -102118,13 +102491,13 @@ ${getInterRoleHandoffRule()}
102118
102491
  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
102492
  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
102493
  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:
102494
+ 7. Hand the complete design brief to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102122
102495
 
102123
102496
  \`\`\`bash
102124
102497
  chatroom handoff --chatroom-id="<chatroom-id>" --role="architect" --next-role="{ENTRY_POINT_ROLE}"
102125
102498
  \`\`\`
102126
102499
 
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.`;
102500
+ 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
102501
  });
102129
102502
 
102130
102503
  // ../../services/backend/prompts/cli/roles/builder.ts
@@ -102156,7 +102529,7 @@ ${getInterRoleHandoffRule()}
102156
102529
  4. Label every finding \`confirmed\`, \`inferred\`, or \`unknown\`. Never present a guess as fact.
102157
102530
  5. Resolve ambiguity where evidence allows. For the rest, state the open question, who must decide it, and a recommended default.
102158
102531
  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:
102532
+ 7. Hand the brief to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102160
102533
 
102161
102534
  \`\`\`bash
102162
102535
  chatroom handoff --chatroom-id="<chatroom-id>" --role="researcher" --next-role="{ENTRY_POINT_ROLE}"
@@ -102169,7 +102542,7 @@ var init_triage3 = __esm(() => {
102169
102542
  init_sections();
102170
102543
  TRIAGE_GUIDANCE = `## Triage Operating Model
102171
102544
 
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.
102545
+ 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
102546
 
102174
102547
  ${"{SESSION_CONTINUITY}"}
102175
102548
 
@@ -102179,7 +102552,7 @@ ${getInterRoleHandoffRule()}
102179
102552
  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
102553
  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
102554
  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:
102555
+ 5. Hand the report to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102183
102556
 
102184
102557
  \`\`\`bash
102185
102558
  chatroom handoff --chatroom-id="<chatroom-id>" --role="triage" --next-role="{ENTRY_POINT_ROLE}"
@@ -102204,20 +102577,19 @@ ${getInterRoleHandoffRule()}
102204
102577
  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
102578
  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
102579
  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:
102580
+ 7. Hand the complete design brief to \`{ENTRY_POINT_ROLE}\` with the normal command, then stop:
102208
102581
 
102209
102582
  \`\`\`bash
102210
102583
  chatroom handoff --chatroom-id="<chatroom-id>" --role="uiux-engineer" --next-role="{ENTRY_POINT_ROLE}"
102211
102584
  \`\`\`
102212
102585
 
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.`;
102586
+ 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
102587
  });
102215
102588
 
102216
102589
  // ../../services/backend/prompts/cli/roles/verifier.ts
102217
102590
  var ACHIEVED2, NOT_ACHIEVED2, INCONCLUSIVE2, VERIFIER_GUIDANCE;
102218
102591
  var init_verifier3 = __esm(() => {
102219
102592
  init_verifier_handoff_templates();
102220
- init_chat_handoff_template();
102221
102593
  init_handoff_report_template_body();
102222
102594
  init_sections();
102223
102595
  [ACHIEVED2, NOT_ACHIEVED2, INCONCLUSIVE2] = VERIFIER_VERDICTS;
@@ -102237,7 +102609,7 @@ ${getInterRoleHandoffRule()}
102237
102609
  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
102610
  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
102611
  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:
102612
+ 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
102613
 
102242
102614
  \`\`\`bash
102243
102615
  chatroom handoff --chatroom-id="<chatroom-id>" --role="verifier" --next-role="{ENTRY_POINT_ROLE}"
@@ -102270,6 +102642,7 @@ var init_fromContext2 = __esm(() => {
102270
102642
  init_uiux_engineer3();
102271
102643
  init_verifier3();
102272
102644
  init_fromContext();
102645
+ init_handoff_templates3();
102273
102646
  });
102274
102647
 
102275
102648
  // ../../services/backend/prompts/teams/duo/prompts/builder.ts
@@ -102381,7 +102754,7 @@ var init_templates = __esm(() => {
102381
102754
  "Attempt to reproduce the issue with the smallest focused automated test and report the result honestly",
102382
102755
  "Recommend the smallest immediate fix without implementing it",
102383
102756
  "Report systemic design risks separately from the immediate fix",
102384
- "Hand the complete investigation report to the configured entry point"
102757
+ "Hand the complete investigation report to the planner"
102385
102758
  ],
102386
102759
  defaultHandoffTarget: "planner"
102387
102760
  },
@@ -138304,37 +138677,29 @@ teamCommand.command("set").description("Set the team preset for a chatroom").req
138304
138677
  const { setTeam: setTeam2 } = await Promise.resolve().then(() => (init_team(), exports_team));
138305
138678
  await setTeam2(options.chatroomId, options.team);
138306
138679
  });
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) {
138680
+ 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
138681
  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
138682
  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
- }
138683
+ printHandoffViewTemplate2({
138684
+ from: options.from,
138685
+ to: options.to,
138686
+ mode: options.mode,
138687
+ teamId: options.teamId,
138688
+ legacyRole: parentOpts.role,
138689
+ legacyNextRole: parentOpts.nextRole
138690
+ });
138324
138691
  });
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) {
138692
+ 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
138693
  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
138694
  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
- }
138695
+ printHandoffListTemplates2({
138696
+ from: options.from,
138697
+ to: options.to,
138698
+ mode: options.mode,
138699
+ teamId: options.teamId,
138700
+ legacyRole: parentOpts.role,
138701
+ legacyNextRole: parentOpts.nextRole
138702
+ });
138338
138703
  });
138339
138704
  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
138705
  const missing = [
@@ -138776,4 +139141,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
138776
139141
  });
138777
139142
  program2.parse();
138778
139143
 
138779
- //# debugId=BF04636703AF51D164756E2164756E21
139144
+ //# debugId=430CD3ADC73C742264756E2164756E21