qv-devops-daily-update
Skill697 starsChanged 18 days agoApache-2.0View on GitHub
Compose a daily standup in the team's Slack format (π¨ Done today / π Planned for tomorrow / π§ Blockers / risks), aggregating recent PRs, reviews, and CI from tetherto/qvac. Use when asked for a daily update, standup, EOD, or invoking /qv-devops-daily-update.
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 2 are distinctive, and 10 are very specific to this project.
β0
Common Β· estimate
Many files like this have a rule of this kind.
β2
Distinctive Β· estimate
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 33
If the user did not specify, default to yesterday 00:00 / slack.
- Distinctive: line 41
Write secrets to any output (the assembler runs a regex scrub before file write.
- Very specific: line 97
If pr-status.mjs stderr contains SLACK_VALIDATION_REQUIRED, follow the validation gate in pr-mine's workflow (step 2).
- Very specific: line 124
If the Asana MCP is available and --no-asana was not passed, call the appropriate tool (read the descriptor first per the β¦
- Very specific: line 131
If Asana is unavailable or --no-asana is set, skip this step.
- Very specific: line 135
Before writing /tmp/devops-daily-update-<YYYY-MM-DD>.txt, run a regex check on every PR title, branch name, run name, Asana task title, and β¦
- Very specific: line 141
If any string matches, redact the matching span ([REDACTED]) and add a chat-only note: "Daily update redacted N suspicious tokens β review β¦
- Very specific: line 153
If the PR title has no ticket, extract from the head branch name (e.g., feat/QVAC-12345-thing).
- Very specific: line 154
If still no ticket, fall back to #<pr-number> as the leading label.
- Very specific: line 195
If the user requested --format markdown, save the Markdown form to the temp file too.
- Very specific: line 206
Do NOT pre-link ticket numbers via <URL|TICKET> β the workspace's Asana app handles auto-linking.
- Distinctive: line 222
Before printing the output, verify:
β βCommonβ is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. βVery specificβ is our guess from the words: it names a file, a command, a setting or the project itself.
Files
DevOps Daily Update
Composes a standup / EOD update in the team's standard Slack format and writes it to a temp file ready to paste. Sourced from the user's GitHub activity in tetherto/qvac plus optional Asana context.
The skill is read-only with respect to GitHub state and the local working tree. It NEVER posts the message β the user copies it manually. The canonical Slack form is documented in Step 8.
When to use this skill
Use when:
- User asks for a "daily update", "standup", "EOD", or "what did I do yesterday?"
- User invokes
/qv-devops-daily-update - User asks to draft a status post for the team channel
Prerequisites
ghCLI installed and authenticated (gh auth status)- User has access to
tetherto/qvac - Optional: Asana MCP available β surfaces today's assigned tasks (degrades gracefully if not)
Inputs
- Optional:
--since <ISO date | Nd | Nw>β defaults to yesterday 00:00 in the user's local timezone. The default 24-hour lookback works for both EOD posts (late evening) and morning standups; extend it for Monday-after-weekend (--since 3d) or post-holiday (--since 1w). - Optional:
--format slack | markdownβ defaults toslack. The Slack form is what gets pasted; Markdown is the chat preview form (**bold**,[text](URL)) and is also accepted by Asana rich-text comments. - Optional:
--no-asanaβ skip the Asana lookup even if the MCP is available.
If the user did not specify, default to yesterday 00:00 / slack.
Safety rules
This skill is read-only. It does NOT:
- Modify the user's working tree, branch, or any file under
~/.cache/ - Post to Slack, Asana, or GitHub
- Write secrets to any output (the assembler runs a regex scrub before file write; see step 7)
The skill MAY write its assembled output to /tmp/devops-daily-update-<YYYY-MM-DD>.txt so the user can pbcopy < <path>. The extension is .txt (not .md) because the canonical form is Slack mrkdwn, not GitHub-flavored Markdown.
Efficiency rules
Total shell calls per run: β€ 6 (one per data source + one for the timestamp + one to write the temp file). Cache gh api user and reuse via Read for the rest of the session. If a data source errors (e.g., Asana MCP not configured), continue with that section's items missing from the aggregate rather than failing the whole skill β the canonical form does not have an "Asana" section, so missing Asana data only thins out the bullet pools, not the layout.
Workflow
1. Resolve the lookback window
SINCE="$(date -u -v-1d -j -f "%Y-%m-%d" "$(date -u +%Y-%m-%d)" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
|| date -u -d 'yesterday 00:00' +%Y-%m-%dT%H:%M:%SZ)"
echo "$SINCE"Parse --since if provided (Nd β N days, Nw β N weeks, ISO date β that date 00:00 UTC).
2. Resolve the current user
gh api user --jq '.login' > /tmp/devops-daily-update-user.txtReuse via Read for the rest of the run.
3. Pull recently-merged PRs (mine)
gh search prs \
--repo tetherto/qvac \
--author "@me" \
--merged-at ">=$SINCE" \
--json number,title,url,closedAt \
--limit 30 \
> /tmp/devops-daily-update-merged.jsonThese feed π¨ Done today. gh search prs --json does not expose mergedAt, additions, or deletions β only closedAt is available, and the --merged-at ">=$SINCE" filter already guarantees the result set is merged-in-window. If size signal is needed for the bullet wording, fetch it per-PR via gh pr view <num> --json additions,deletions (one extra call per PR β only do this when the user asks for it).
4. Pull my open PRs and reviews owed
node .agents/skills/_lib/pr-skills/pr-status.mjs --mode my \
> /tmp/devops-daily-update-my.txt 2> /tmp/devops-daily-update-my.stderr
gh search prs \
--repo tetherto/qvac \
--review-requested "@me" \
--state open \
--json number,title,url,author,updatedAt \
--limit 30 \
> /tmp/devops-daily-update-reviews-owed.jsonIf pr-status.mjs stderr contains SLACK_VALIDATION_REQUIRED, follow the validation gate in pr-mine's workflow (step 2). Do not present the daily update until the gate clears.
Output routing:
- Open PRs I authored that received commits since
$SINCE(i.e., I pushed work on them today) βπ¨ Done todaywith the actionaddressed comments on the PR(when the recent commits follow a review event) orpushed updates on <topic>(otherwise). - Open PRs I authored without recent commits β
π Planned for tomorrowwith the actioncontinue / wrap up <topic>. - Reviews owed (
--review-requested "@me") βπ Planned for tomorrowasreview #<num> β <title> by <author>. Cap surfaced reviews at 5 (sorted byupdatedAtdesc β most recent first); if the queue is longer, append a single line(+N more review requests in queue β run /qv-devops-pr-status for the full list). A standup with 30 review-bullets is unreadable. - Open PRs I authored with
mergeable: CONFLICTINGβπ§ Blockers / risksasconflicts on #<num> β needs rebase. - Open PRs I authored with stale review requests (no review activity in >3 days) β
π§ Blockers / risksasstale review on #<num> β pinged <reviewer> on <date>.
5. Pull recent CI runs (filter to mine)
gh run list does not have an author filter. Approximate the user's runs by scoping to recent PR head branches:
gh run list \
--repo tetherto/qvac \
--created ">=$SINCE" \
--limit 50 \
--json conclusion,event,headBranch,name,url,workflowName,headSha,displayTitle \
> /tmp/devops-daily-update-runs.jsonFilter client-side: keep runs where headBranch matches one of the user's PRs from steps 3 or 4. Failed runs feed π§ Blockers / risks as CI failing on #<num> β <workflowName>. In-progress / queued runs are NOT surfaced (too noisy for a daily update).
6. (Optional) Pull today's Asana tasks
If the Asana MCP is available and --no-asana was not passed, call the appropriate tool (read the descriptor first per the agentic-automation rule) to fetch the user's tasks. Filter to:
- Status = in-progress or due today/tomorrow β feed
π Planned for tomorrowas<TICKET>: <task title> - Status = blocked β feed
π§ Blockers / risksas<TICKET>: blocked β <reason from notes>
Asana tickets in the QVAC project follow the QVAC-\d+ format and slot directly into the bullet shape.
If Asana is unavailable or --no-asana is set, skip this step. The output will rely on GitHub-derived items only.
7. Run a secret-pattern scrub on every assembled string
Before writing /tmp/devops-daily-update-<YYYY-MM-DD>.txt, run a regex check on every PR title, branch name, run name, Asana task title, and any user-provided extras:
(sk_live_|AIza[0-9A-Za-z\-_]{35}|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|gho_|github_pat_|xoxb-|-----BEGIN [A-Z ]+ KEY-----)If any string matches, redact the matching span ([REDACTED]) and add a chat-only note: "Daily update redacted N suspicious tokens β review the source PRs/runs manually." Never include the raw matched string anywhere in the output, the chat preview, or the temp file.
8. Assemble the output
Build the message in two forms:
- Slack form (the canonical, matches the team template), saved to
/tmp/devops-daily-update-<YYYY-MM-DD>.txt. - Markdown form (for chat preview only), printed in chat.
Each item from steps 3β6 must be normalized to a TICKET: action bullet. Ticket extraction rules:
- Extract
QVAC-\d+(or[A-Z]+-\d+) from the PR title; that's the ticket. - If the PR title has no ticket, extract from the head branch name (e.g.,
feat/QVAC-12345-thing). - If still no ticket, fall back to
#<pr-number>as the leading label. - The action is the PR-title subject (the part after
prefix[tags]:), past tense forDone today, action-verb-leading forPlanned for tomorrow. Drop theprefix[tags]:from the rendered action. - Sub-bullets are added when (a) the user provided extra context for that item, or (b) more than one PR shares the same ticket β the parent line is the ticket, sub-bullets are each PR.
Slack form (canonical)
π¨ *Done today*
- <TICKET-or-#num>: <past-tense action>
- ...
- <optional sub-bullet>
π
*Planned for tomorrow*
- <TICKET-or-#num>: <forward-looking action>
- ...
π§ *Blockers / risks*
- N/AEmpty section β single bullet - N/A (literal). Three sections always rendered, in this order, separated by a single blank line. Bare ticket bullets (- QVAC-13860 with no : and no action) are allowed when the work is self-evident from the ticket title.
Markdown form (chat preview only)
**π¨ Done today**
- <TICKET-or-#num>: <past-tense action>
- ...
**π
Planned for tomorrow**
- <TICKET-or-#num>: <forward-looking action>
- ...
**π§ Blockers / risks**
- N/A(Same content, GitHub-flavored Markdown rendering for the chat preview only.)
Format-conversion cheatsheet
If the user requested --format markdown, save the Markdown form to the temp file too. Conversion rules between the two forms:
| Markdown | Slack |
**X** | *X* |
*X* (italic) | _X_ |
[text](URL) | <URL|text> |
# H1 / ## H2 | not used (use Slack-bold instead) |
Plain QVAC-\d+ | Plain QVAC-\d+ (the workspace's Slack/Asana integration auto-links) |
4-space-indented - sub | 4-space-indented - sub (Slack respects 4-space indent for sub-bullets) |
Do NOT pre-link ticket numbers via <URL|TICKET> β the workspace's Asana app handles auto-linking. Pre-linking conflicts with that and renders awkwardly.
9. Print the result
- Print the Markdown form in a fenced code block in chat for the user to scan.
Print the path to the Slack-form temp file with copy commands:
pbcopy < /tmp/devops-daily-update-<YYYY-MM-DD>.txt # macOS xclip -selection clipboard < /tmp/devops-daily-update-<YYYY-MM-DD>.txt # Linux- Offer: "Edit any line before posting? Tell me which ticket and the new action wording, and I'll regenerate."
Quality Checklist
Before printing the output, verify:
- Three sections rendered, in order: π¨ Done today / π Planned for tomorrow / π§ Blockers / risks
- Section headings use the exact emoji and the exact section names from the canonical template
- Empty sections render as a single
- N/Abullet (never_(none)_, never empty, never removed) - Every bullet leads with
TICKET:(or#<pr-num>:only when no ticket could be extracted) - No bullet prefixes, no severity tags, no PR-state tags (
[needs-review],[ready], etc.) β that meta is folded into prose actions - Each
Done todayitem is genuinely activity since$SINCE(merged PR, pushed commits, etc. β not stale) - Each
Planned for tomorrow β reviewitem is open and the user is inrequestedReviewers - Each
Blockers / risks β CI failingitem is on a PR the user authored or a branch they own - No raw secret-shaped strings made it through the scrub
- Slack form has no Markdown headings, no
**bold**(uses*bold*), no GitHub-style links - Temp-file path matches the day's local-tz ISO date
References
- GitHub and CI guidance: .github/AGENTS.md
- Cross-pod my-PRs skill: .agents/skills/qv-pr-mine/SKILL.md
- DevOps PR status skill: .agents/skills/qv-devops-pr-status/SKILL.md
- Pod metadata: .github/teams/devops.json
In this repository56 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .github/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/agent-integrations.mdcCursor rule
- .cursor/rules/cpp/string-api-conventions.mdcCursor rule
- .cursor/rules/devops/main.mdcCursor rule
- .cursor/rules/no-remote-code-execution.mdcCursor rule
- .cursor/rules/qip-triage.mdcCursor rule
- .cursor/rules/sdk/commit-and-pr-format.mdcCursor rule
- .cursor/rules/sdk/error-handling.mdcCursor rule
- .cursor/rules/sdk/first-class-product-parity.mdcCursor rule
- .cursor/rules/sdk/main.mdcCursor rule
- .cursor/rules/sdk/public-constants-contract.mdcCursor rule
- .cursor/rules/sdk/request-lifecycle-primitives.mdcCursor rule
- .cursor/rules/sdk/sdk-pod-packages.mdcCursor rule
- .cursor/rules/sdk/skill-authoring-guidelines.mdcCursor rule
- cpp-string-api-reviewSkill
- qv-addon-changelogSkill
- qv-addon-pr-createSkill
- qv-addon-release-notesSkill
- qv-agent-stack-syncSkill
- qv-asana-syncSkill
- qv-daily-work-updateSkill
- qv-dev-diary-setupSkill
- qv-dev-diarySkill
- qv-devops-pr-createSkill
- qv-devops-pr-reviewSkill
- qv-devops-pr-statusSkill
- qv-devops-runner-queueSkill
- qv-devops-why-my-pr-notSkill
- qv-docs-solution-createSkill
- qv-docs-updateSkill
- qv-holepunch-devSkill
- qv-merge-guard-wireSkill
- qv-mobile-test-dispatchSkill
- qv-notice-generateSkill
- qv-pr-mineSkill
- qv-pr-reviewSkill
- qv-pr-testSkill
- qv-qip-createSkill
- qv-qip-reviewSkill
- qv-qip-triageSkill
- qv-quality-reportingSkill
- qv-registry-autobase-patternsSkill
- qv-release-trainSkill
- qv-sdk-backmergeSkill
- qv-sdk-changelogSkill
- qv-sdk-e2e-createSkill
- qv-sdk-inference-versionSkill
- qv-sdk-pr-createSkill
- qv-sdk-pr-statusSkill
- qv-sdk-update-modelsSkill
- qv-skill-listSkill
- setupSkill
- setupSkill
- qv-nx-ciSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

