{
 "id": "5.9",
 "title": "Briefs and hand-off",
 "department": "Engineering",
 "department_slug": "engineering",
 "direction": null,
 "branded": false,
 "status": "draft",
 "owner": "Param",
 "last_verified": "Mon Oct 26",
 "holds": "Team brief, jam brief, hand-off page, recipients, send routes",
 "urls": {
  "html": "https://handbook.joinsquareup.com/engineering/briefs-and-hand-off",
  "markdown": "https://handbook.joinsquareup.com/engineering/briefs-and-hand-off.md",
  "json": "https://handbook.joinsquareup.com/engineering/briefs-and-hand-off.json"
 },
 "other_directions": [],
 "tldr": {
  "headline": "Every jam ends in a brief someone else can work from",
  "points": [
   {
    "icon": "book",
    "text": "Three documents: the jam brief, a team brief per deliverable, and a signed read only page."
   },
   {
    "icon": "people",
    "text": "The Send to sheet names one of seven recipients."
   },
   {
    "icon": "lock",
    "text": "Brew emails a brief only to our team; it never posts or runs anything."
   },
   {
    "icon": "box",
    "text": "Also a PDF, a publish pack, and Gmail, Mail or Outlook drafts."
   },
   {
    "icon": "gear",
    "text": "Bump TB_V when briefs are written differently, and all saved ones rewrite."
   }
  ],
  "stat": null,
  "decide": "Should shared links expire? Proposal: 30 days by default, with revoke on the jam.",
  "mood": "solid"
 },
 "sources": [
  "brew origin/main: jam-brief.js:1-8; team-brief.js:1-20, 196-223; handoff.js:1-20; brief-status.js:1-10; jam-mail.js:1-8, 104, 117; jam2/ready.js:10-11; publish-pack.js:1-5",
  "brew origin/main: SCOPE.md (Share the brief, Brew's emails); DUMMY.md (closing paragraph)",
  "brew origin/main: docs/handover/engineering/12-ui2-service-api.md section 1, 13-jam-chip-api.md",
  "brew origin/main git log: 9fd1de4 (per-tab briefs with recipients)",
  "memory brew-brief-mode, brew-team-brief-ai-edit, brew-jam-rca-2026-10-26, brew-real-connectors"
 ],
 "open_questions": [
  "**Should shared links expire?** Proposal: 30 days by default, with revoke on the jam.",
  "**Does the recipient \"our team\" stay now that Brew is kept independent?** Proposal: keep it as is, add nothing new tied to it. [src: memory brew-qa-round2-2026-10-24]"
 ],
 "parts": {
  "Answer": "Every jam ends in a brief someone else works from: the jam brief (the working document), the team brief (one per deliverable, written for a named recipient), a signed read-only page, a PDF and a publish pack; Brew sends the brief only to our team by email and never posts or runs anything itself.",
  "Today": "### Three documents\n\n| Document | What it is | Where it lives | Source |\n|---|---|---|---|\n| Jam brief | One Markdown document per jam (`w.doc`): starts as the card, grows as people jam, AI edits on request, replies fold in; readiness is a checklist, never a score | the jam | [src: brew/jam-brief.js:1-6] |\n| Team brief | One AI pass turns the card, proof, plan, jam brief and final package into a brief with fixed editable sections and evidence per claim; final words verbatim; creatives attached | `w.teamBriefs[changeId]`, one per deliverable tab (`?ch=`) | [src: brew/team-brief.js:1-7, 196-200] [src: git 9fd1de4] |\n| Hand-off | Everything about a jam for someone outside: card, options, Plays, brief, versions, assets, chats, open questions | `/h/<token>` read-only page, signed | [src: brew/handoff.js:1-10] |\n\n`TB_V` 4: bump it when the team brief starts being written differently; every saved one is rewritten. [src: brew/team-brief.js:17]\n\n### Recipients\n\nThe \"Send to…\" sheet names a real recipient: your team, your agency, a designer, a media buyer, a creator, a video editor, or our team. [src: brew/team-brief.js:20] [src: memory brew-jam-rca-2026-10-26]\n\n### Send routes\n\n| Route | What happens | Source |\n|---|---|---|\n| Share with my team | Freezes the brief (BR-n, numbered per brand), copies it with the read-only link; nothing sent | [src: brew/SCOPE.md] [src: brew/docs/handover/engineering/11-known-issues-and-debt.md] |\n| Send to our team | Freezes and emails the whole brief to `SHOPOS_EMAIL` (default hello@joinsquareup.com) every time; tracked status | [src: brew/jam-mail.js:104] [src: brew/brief-status.js:1-6] |\n| Download PDF | Chromium render, `gen/brief-*.pdf` | [src: memory brew-brief-mode] |\n| Open in Gmail, Mail or Outlook | Downloads the files and opens a compose page or an .eml draft from the person's own email; no Gmail scope | [src: memory brew-brief-mode] |\n| Slack | Posts to the channel picked at connect with an Approve button; thread replies fold into the brief | [src: memory brew-real-connectors] |\n| Publish pack | A zip per version for the team to post or apply by hand | [src: brew/publish-pack.js:1-5] |\n\n### Status of a brief sent to our team\n\n`sent → received → in_progress → delivered`, or `needs_info` (needs a note) and back. Only staff move it (`POST /api/work/:wid/brief/status`). Each move writes a jam line, a notification and an email to the sender; the top bar shows \"N with the team\". If the email did not go, the jam says \"ready, paste it\", never \"sent\". [src: brew/brief-status.js:1-10] [src: brew/docs/handover/engineering/12-ui2-service-api.md]\n\n### Editing a brief\n\nThe team brief writes itself once the first draft is in. Selecting text or tapping a section opens \"Change with AI\"; there are no hand-edit boxes. Chat edits the brief only when the message is about the brief. Every change stamps a revision so teammates reload it. [src: memory brew-team-brief-ai-edit] In the Brief tab, people can comment on words and press \"Fix with AI\". [src: memory brew-brief-mode]\n\n### Link signing\n\nHand-off and ready links are HMAC-signed with `HANDOFF_SECRET` (production uses its own and opens nothing signed with the Anthropic key). The signature is 12 base64url characters. Links do not expire. [src: brew/handoff.js:14-20] [src: brew/jam2/ready.js:10-11]\n\n### Guests\n\nGuests cannot share, send or move a brief. The demo site sends no email. [src: brew/SCOPE.md]",
  "Tomorrow": "| Item | Version | Tag |\n|---|---|---|\n| One team brief per deliverable with a named recipient | v1 | Stays |\n| Brew never sends to a brand's customers | v1 | Stays |\n| Links that expire and can be revoked | v2 | New |\n| Sending a brief to an agency by email from Brew | v2 | New, needs a send decision |\n| Posting the final asset to the channel | v3 | New, only behind a person's yes |",
  "How we do it": "1. A new brief kind gets its own sections in `team-brief.js` and a test in `test/team-brief.test.js`.\n2. Never let the fact sheet or team-only card words into a shared brief; `unleak()` and `publicView` guard this. [src: memory brew-brief-mode] [src: memory brew-shopify-connector-qa]\n3. Check a status change end to end on staging with a staff account before relying on it.",
  "Numbers": "| Metric | Definition | Where measured |\n|---|---|---|\n| Briefs shared | Frozen briefs per brand per week | `w.jamBrief` (Proposed to count) |\n| With our team | Briefs sent and not yet delivered | `withTeam.n` on `/feed` and `/work` [src: brew/docs/handover/engineering/12-ui2-service-api.md] |\n| Time to delivered | Sent to delivered, per brief | `w.jamBrief.history` (Proposed) |",
  "Open": "1. **Should shared links expire?** Proposal: 30 days by default, with revoke on the jam.\n2. **Does the recipient \"our team\" stay now that Brew is kept independent?** Proposal: keep it as is, add nothing new tied to it. [src: memory brew-qa-round2-2026-10-24]"
 }
}