--- description: Automated standup generation. Parallel data fetch from Linear, GitHub, Slack, Calendar, then synthesize, refine with user, and post to Slack. category: verkada --- flowchart TD _HEADER_["
Verkada Standup
Automated standup generation. Parallel data fetch from Linear, GitHub, Slack, Calendar, then synthesize, refine with user, and post to Slack.
"]:::headerStyle classDef headerStyle fill:none,stroke:none subgraph _MAIN_[" "] %% Phase 1: Parallel Data Fetch subgraph Fetch["Phase 1: Parallel Data Fetch"] SCRIPT[standup-data.py] --> LINEAR_P[Linear Projects
+ Tickets] & GH_PRS[GitHub PRs
Merged + Open] & SLACK_MSG[Slack Messages
+ Activity] & CALENDAR[Calendar Events] & USERS[User Directory
UID to Profile] LINEAR_P & GH_PRS & SLACK_MSG & CALENDAR & USERS --> JSON[standup-data.json] end %% Phase 2: Synthesize subgraph Synthesize["Phase 2: Synthesize"] JSON --> DATES[Compute Date Range
Tue/Thu Cadence] DATES --> MATCH[Cross-Reference
PRs to Tickets] MATCH --> CLASSIFY{Classify Items} CLASSIFY --> ASSIGNED[Assigned Work
Project Sections] CLASSIFY --> SELF[Self-Instigated
Initiatives + Tooling] CLASSIFY --> COLLAB[Collaborations
Cross-Team Only] CLASSIFY --> BUGS[Bugs Fixed] ASSIGNED & SELF & COLLAB & BUGS --> TOP3[Select Top 3
Highlights] TOP3 --> DRAFT[Format Standup
Slack mrkdwn] end %% Phase 3: Refine subgraph Refine["Phase 3: User Refinement"] DRAFT --> PRESENT[Present to User] PRESENT --> FEEDBACK{User Feedback?} FEEDBACK -->|Remove items| EDIT_RM[Remove + Re-present] FEEDBACK -->|Reword items| EDIT_RW[Reword + Re-present] FEEDBACK -->|Add missing| EDIT_ADD[Add + Re-present] FEEDBACK -->|Other| EDIT_OTHER[Apply + Re-present] EDIT_RM & EDIT_RW & EDIT_ADD & EDIT_OTHER --> PRESENT FEEDBACK -->|Looks good| CONFIRM{Post to Slack?} CONFIRM -->|No| CANCEL([Cancelled]) end %% Phase 4: Post subgraph Post["Phase 4: Post to Slack"] CONFIRM -->|Yes| TOP_MSG[Post Top-Level
Date + Top 3] TOP_MSG --> THREAD[Post Thread Reply
Full Details] THREAD --> DONE([Posted to
#access-ship-standup]) end click SCRIPT "#" "**standup-data.py**\nParallel data capture script.\nFetches from 5+ sources concurrently via ThreadPoolExecutor in ~10-15 seconds.\n\n`python3 ~/gitea/jset/claude/skills/v-standup/scripts/standup-data.py > /tmp/standup-data.json`\n\nAuto-detects since/until from standup cadence (Tue/Thu).\nOverride: `--since YYYY-MM-DD --until YYYY-MM-DD`" click LINEAR_P "#" "**Linear Projects + Tickets**\nFetches via linear-cli:\n- Active projects (used as section headings)\n- Completed tickets since last standup\n- Active tickets with recent activity\n\nProjects where I'm lead get their own section." click GH_PRS "#" "**GitHub PRs**\nFetches via gh CLI:\n- Merged PRs since last standup\n- Open PRs with recent commits\n- Across all Verkada repos (Backend, Terraform, llm-tools)" click SLACK_MSG "#" "**Slack Messages + Activity**\nFetches via slackctl:\n- Recent messages for initiative/collaboration discovery\n- Activity feed\n\nSurfaces arch discussions, debugging, tool sharing not captured in PRs/tickets." click CALENDAR "#" "**Calendar Events**\nFetches via ekctl:\n- Events between last and next standup\n- Non-recurring meetings are initiative signals\n- Skip recurring standups/lunches/weeklies\n\nUsed to identify what you're driving, not as line items." click USERS "#" "**User Directory**\nUID-to-profile map with:\n- Name, title, division\n- `is_internal` flag (SW Access Control = internal)\n\nInternal team members are skipped in Collaborations.\nOnly cross-team people are listed." click JSON "#" "**standup-data.json**\nSingle JSON blob at `/tmp/standup-data.json`.\nContains: meta (dates), projects, merged_prs, completed_tickets, active_tickets, open_prs, slack_messages, slack_activity, calendar_events, user_directory." click DATES "#" "**Compute Date Range**\nStandup cadence: Tuesday and Thursday.\n- Mon/Tue: since last Thu\n- Wed/Thu: since last Tue\n- Fri/Sat/Sun: since last Thu\n\nAll data is filtered to this window." click MATCH "#" "**Cross-Reference PRs to Tickets**\nPair PRs with Linear tickets by:\n1. Ticket ID in PR title: `[ACBE-1234]`\n2. PR URL in ticket attachments/comments\n3. Keyword overlap as fallback\n\nCombined items get both links in the standup." click CLASSIFY "#" "**Classify Items**\nEach item goes in exactly ONE section (no double-counting):\n- Assigned work (tickets, deliverables) -> project sections or Bugs Fixed\n- Self-instigated (tooling, cleanup, docs) -> Initiatives or Tooling\n- Cross-team meetings/advising -> Collaborations\n- Longer-term architecture -> Ongoing" click ASSIGNED "#" "**Assigned Work**\nProject deliverables grouped by Linear project.\nOnly create a section for projects with actual activity.\n\nExamples: Automations, Scenarios, SA2.0" click SELF "#" "**Self-Instigated**\n*Initiatives:* Code cleanup campaigns, documentation, self-filed investigations.\n*Tooling:* Internal tools you built (verkurl, alert monitoring).\n\nDemonstrates value beyond assigned work." click COLLAB "#" "**Collaborations**\nCross-team only -- skip internal AC team members.\nInclude: person's name, team, what you worked on.\nFold upcoming cross-team meetings with date notes.\n\nUse user_directory to filter internal vs external." click BUGS "#" "**Bugs Fixed**\nAssigned bug tickets resolved since last standup.\nBe specific about impact:\n'Root-caused delayed unlock affecting hundreds of doors'\nnot 'fixed a bug'." click TOP3 "#" "**Top 3 Highlights**\nSelect the 3 most impactful items across all sections.\nThese appear first, before any section details.\n\nChoose items a manager or skip-level would care about most.\nConcise single-line summaries, no links needed here." click DRAFT "#" "**Format Standup**\nSlack mrkdwn format (not markdown):\n- Bold: `*text*` (single asterisks)\n- Bullets: bullet character, not dashes\n- Links: ``\n- Lines under 80 chars (excluding URL tags)\n\nIC voice: 'driving', 'planning', 'advising' -- never 'led'." click PRESENT "#" "**Present to User**\nShow the complete standup summary.\nUser reviews before posting." click FEEDBACK "#" "**User Feedback**\nMultiSelect checkboxes via AskUserQuestion:\n- 'Looks good, post to Slack'\n- 'Remove some items'\n- 'Reword items'\n- 'Add missing items'\n- 'Other' (free-form)\n\nLoop until 'Looks good' is selected." click EDIT_RM "#" "**Remove Items**\nAsk which items to cut.\nRe-present the complete updated standup." click EDIT_RW "#" "**Reword Items**\nAsk which items to rephrase.\nRe-present the complete updated standup." click EDIT_ADD "#" "**Add Missing**\nAsk what to add.\nRe-present the complete updated standup." click EDIT_OTHER "#" "**Other Feedback**\nApply free-form feedback.\nRe-present the complete updated standup." click CONFIRM "#" "**Post to Slack?**\nFinal confirmation via AskUserQuestion:\n'Post this standup to #access-ship-standup?'\n- 'Yes, post it'\n- 'No, cancel'\n\nNEVER post without explicit 'Yes' confirmation." click TOP_MSG "#" "**Post Top-Level Message**\nMessage 1 in #access-ship-standup (C03K7ED7J4F):\n\n`Since last standup on YYYY-MM-DD`\n`Top 3:`\n`1. [highlight]`\n`2. [highlight]`\n`3. [highlight]`\n`_Full details in thread_ :thread:`\n\nCapture the returned timestamp for threading." click THREAD "#" "**Post Thread Reply**\nMessage 2 as a thread reply using the timestamp:\n`slackctl send 'C03K7ED7J4F' 'FULL_DETAILS' --thread 'TIMESTAMP'`\n\nContains all sections (Bugs, Projects, Ongoing, Initiatives, Collaborations, Tooling).\nDoes NOT repeat the Top 3." click DONE "#" "**Posted**\nStandup posted to #access-ship-standup as a two-message thread.\nTop-level: date + Top 3 highlights.\nThread: full categorized details with hyperlinked tickets and PRs." click CANCEL "#" "**Cancelled**\nUser declined to post. Standup text is still available for manual posting or further editing." classDef fetch fill:#d1ecf1,stroke:#7ec8d8 classDef synthesize fill:#e8daef,stroke:#b07cc6 classDef refine fill:#fff3cd,stroke:#f0c040 classDef post fill:#dfe6ff,stroke:#5b7bce classDef approved fill:#d4edda,stroke:#5cb85c classDef cancelled fill:#f8d7da,stroke:#e06070 class SCRIPT,LINEAR_P,GH_PRS,SLACK_MSG,CALENDAR,USERS,JSON fetch class DATES,MATCH,CLASSIFY,ASSIGNED,SELF,COLLAB,BUGS,TOP3,DRAFT synthesize class PRESENT,FEEDBACK,EDIT_RM,EDIT_RW,EDIT_ADD,EDIT_OTHER,CONFIRM refine class TOP_MSG,THREAD post class DONE approved class CANCEL cancelled end style _MAIN_ fill:none,stroke:none,padding:0 _HEADER_ ~~~ _MAIN_