{"record":{"id":"e86b97a44537471c","repo":"nexu-io/open-design","slug":"this-open-design-brief-was-already-confirmed-with","errorCode":null,"errorMessage":"This Open Design brief was already confirmed with different answers.","messagePattern":"This Open Design brief was already confirmed with different answers\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"apps/daemon/src/mcp-brief.ts","lineNumber":463,"sourceCode":"      const submittedAnswers = readAnswerRecord(input.answers, 'answers');\n      const mergedAnswers: UnknownRecord = {\n        ...draft.knownAnswers,\n        ...submittedAnswers,\n      };\n      const decision = collectOpenDesignBrief({\n        artifactType: draft.artifactType,\n        knownAnswers: mergedAnswers,\n      });\n      if (!decision.complete) {\n        const missing = decision.questions.map((question) => question.id);\n        throw new Error(\n          `The Open Design brief is incomplete. Missing: ${missing.join(', ')}.`,\n        );\n      }\n      const confirmationAnswersDigest = stableAnswerDigest(decision.answers);\n      if (draft.confirmation) {\n        if (draft.confirmationAnswersDigest !== confirmationAnswersDigest) {\n          throw new Error(\n            'This Open Design brief was already confirmed with different answers.',\n          );\n        }\n        return draft.confirmation;\n      }\n\n      const confirmationLocale =\n        draft.localeSource === 'fallback'\n          ? readBriefLocale(input.locale)\n          : draft.locale;\n      const confirmation: LocalMcpBriefConfirmation = {\n        view: 'brief-confirmed',\n        artifactType: draft.artifactType,\n        projectTitle: draft.projectTitle,\n        locale: confirmationLocale,\n        briefDraftId,\n        briefConfirmationId: randomUUID(),\n        confirmedAt: at,","sourceCodeStart":445,"sourceCodeEnd":481,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/mcp-brief.ts#L445-L481","documentation":"A draft may be confirmed more than once but only idempotently: once draft.confirmation is set, every later confirm must reproduce the same answer set. stableAnswerDigest serializes answers (entries sorted by key, values spread) and compares; any difference throws. This prevents a confirmed brief from being silently re-answered.","triggerScenarios":"Calling confirm_brief twice on the same briefDraftId with different option selections; re-confirming after the user changed an answer but reused the draft.","commonSituations":"Retry logic that mutates answers between attempts; a UI back button that edits then re-submits on the same draft.","solutions":["If the answers legitimately changed, call collect_brief again to start a fresh draft and confirm that one.","If retrying the same confirmation, resend the identical answers.","Do not mutate the answer set between confirm attempts on one draft."],"exampleFix":"// before: draft already confirmed with refined-tech, now sending warm-human\nconfirm_brief({ briefDraftId, nonce, answers: { 'website.character': 'warm-human' } })\n\n// after: new intent -> new draft\nconst fresh = await collect_brief({ artifactType: 'website' })\nawait confirm_brief({ briefDraftId: fresh.briefDraftId, nonce: fresh.nonce, answers: { 'website.character': 'warm-human' } })","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await confirmBrief(input);\n} catch (e) {\n  if (/already confirmed with different answers/i.test(e.message)) {\n    const fresh = await collectBrief({ artifactType });\n    return confirmBrief({ ...input, briefDraftId: fresh.briefDraftId, nonce: fresh.nonce });\n  }\n  throw e;\n}","preventionTips":["One draft, one answer set; start a new draft to change answers.","Cache and replay the exact answers that first succeeded for retries.","Never mutate answers between confirm attempts on the same draft."],"tags":["mcp","brief","idempotency","state"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}