agentleFS
joeuk89joeuk89/claude-skills/skills/work-sync/SKILL.md

work-sync

Skill0 starsChanged 29 days agoMITView on GitHub

Use when the user wants their ⚡ Work Notion database brought up to date with reality, a briefing of what needs them, and their standup notes — the morning run. Triggers include "/work-sync", "morning briefing", "work sync", "catch me up", "what's on my plate", "anything need my attention?", "any PRs need my review?", "standup notes", "what did I do yesterday", "full sweep", "triage all my tickets", "clean up my work db", "/work-sync apply" to apply ticked proposals from the latest briefing, and "/work-sync catchup", "what's new", "anything new?", "any new notifications?" for the lighter catch-up pass over new Jira and GitHub activity, runnable any time and as often as wanted. One task the user wants changed on their say-so (status, note, what they did) is work-log, not this.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Jira, GitHub and Slack are read-only. Always: No transitions, comments, reactions, reviews, assignee changes, merges, label edits, marking …

    line 12
  2. Very specific:

    Code state: run the ladder in sources.md against the mapped repo.

    line 70
  3. Very specific:

    Proposals: only the two cases notion.md reserves (closing a ticketless, linkless row.

    line 85

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Work Sync

Bring the ⚡ Work database into line with Jira, GitHub and the repos, log what changed on each task, and publish two things: a standup (what the user did yesterday, what they plan today, blockers) and a briefing (what needs them, who they are waiting on, what the sync did). Runs unattended at 08:00 on weekdays, by hand at any time, and as a lighter catch-up during the day that processes only what arrived since the last run.

Hard rules

  • Jira, GitHub and Slack are read-only. Always. No transitions, comments, reactions, reviews, assignee changes, merges, label edits, marking notifications read, messages or drafts, in any mode including apply. Anything a ticket, PR or Slack thread needs becomes the row's Next step and a briefing line.
  • Notion is the only thing this skill writes, and only the Work, Actions, Briefings and Standups databases. It acts on evidence without asking; the user's own edits are context it reads, not a lock, and an edit of theirs stands until newer evidence contradicts it. The two cases that stay proposals are in references/notion.md.
  • Evidence before claims. A status move needs a changelog entry, a merge needs a compare result, an unanswered question needs the comment quoted. Nothing is "probably merged".

Read first: references/sources.md (Jira, GitHub, Slack, code-state ladder), references/notion.md (schema, matching, write policy, log events), references/repo-map.md, references/briefing.md (Briefings database, page format, ranking, proposal grammar), references/standup.md (Standups database, yesterday's sources, today's list). They are short and every step below leans on them.

Modes

InvocationModeWhat runs
/work-syncdaily, or sweep when today is MondaySteps 1–8 (+ step 6 on Monday)
/work-sync dailydailySteps 1–8, skipping 6
/work-sync sweepsweepSteps 1–8 including 6
/work-sync applyapplyThe apply workflow at the end
/work-sync catchupcatchupSteps 1, 2 (open rows as the match set only), 3 feeds 2–5, 4, 5 and 8 in catch-up shape. No backlog sweep, no standup

"What's new", "anything new?" and "catch me up" mean catchup when a Briefings row already exists for today, otherwise daily. The weekday never upgrades a catch-up to sweep.

Unattended runs reach this skill via scripts/run.sh (launchd). In unattended runs there is nobody to ask: every judgment call becomes a proposal, never a question.

Workflow

1. Anchor the run

  • date "+%A %Y-%m-%d %H:%M %Z" via Bash. Never guess the day.
  • Mode per the table above (an explicit argument wins over the weekday).
  • Identity: atlassianUserInfo once (account ID + display name); gh api user -q .login once. Both drive the own-activity filters.
  • Window start: the Run of the newest Briefings row (query in briefing.md; it comes back in UTC). No row → 08:00 on the previous working day. Convert to UTC for GitHub per sources.md.
  • Standup day: Covers since = the previous working day (Mon → Fri). Independent of the window. Not needed in catchup.
  • Tool availability: Notion MCP missing → stop; the database is the subject. Jira MCP, gh or the Slack tools missing → continue and list the gap under Not verified (when Slack is absent, feed 5 and the standup's Slack source are skipped).

Done when: date, mode, both identities, the window start and Covers since (except in catchup) are known and stated in one line.

2. Load the Work database

Query every row that is not Done (SQL in notion.md) with all properties, plus every Actions row from the window start onward (the dedupe set and the unlinked-entry set). Note which rows have Last Edited later than Last synced: those are user-edited rows. Read their Notes and Status as the user's latest intent; step 5 weighs that against the evidence by timestamp.

Done when: every open row is in a local list with its Jira Code, Link, PR Link, Status, Notes, Since, Last synced, and the user-edited flag.

3. Gather candidates

Build one deduplicated candidate list keyed by Jira key or PR URL. Five feeds, all required:

  1. Every open Work row (from step 2). Verification is unconditional; rows are never skipped for lack of activity. Skipped in catchup: open rows are loaded only as the match set, and a row is verified only when a feed below raises it.
  2. Jira activity in the window: the three JQL queries in sources.md (assigned / reported-or-watched / mention), paginated to the end.
  3. GitHub activity in the window: the notifications feed, reason-filtered, plus the user's own open PRs.
  4. Standing queues (window-independent): open PRs with the user's review requested; tickets assigned to the user in a deploy-ready status; tickets assigned to the user that are overdue or due within 3 days.
  5. Slack asks in the window: the to:me query in sources.md, each hit's thread read, then matched to a candidate by key, PR URL or row title, or raised as a Slack ask of its own. Gathered by the main agent, never a subagent. Skipped when the tools are absent.

A candidate that is already a Work row merges into that row (matching rules in notion.md).

Done when: the list is complete and each entry says which feed(s) raised it.

4. Verify every candidate

For each candidate establish, from evidence:

  • Jira: current status and category, assignee, due date, who commented since the window start and what they said, transitions and assignment changes in the window (changelog), and whether the last comment is a question aimed at the user that nobody has answered.
  • Code state: run the ladder in sources.md against the mapped repo. Record the rung, the PR(s) with state, which PR is the row's PR Link (rule in sources.md), and for changes-requested PRs whether later commits address the threads.
  • Slack: for a candidate feed 5 raised, whether the ask is still unanswered, quoted short with its permalink (rules under "Reading a Slack ask" in sources.md); for a Waiting row, whether the awaited person's reply landed in Slack rather than Jira.
  • Whose move: decide Next step as "Person: action". The deciding question is who has to act for the ticket to progress, never the status name. Deploy-ready assigned to the user → the user's move. In Testing with QA → QA's move. Dev review with a reviewer requested → the reviewer's move. Last comment is the user's question → the person asked.

When more than ten candidates need verification, fan out with the Agent tool: one subagent per repo or project, each returning the compact record defined in sources.md for its items. Subagents are read-only too. Their prompts carry the Atlassian account ID and the GitHub login for the own-activity filter and call the user "the owner"; never their display name or email, which can trip an organisation's AI usage policy and make the subagent refuse. Slack messages a subagent needs are pasted into its prompt as quoted evidence; it never searches Slack itself.

Done when: every candidate has a verified Jira state, a code-state rung (or N/A with the reason) and a Next step with a named owner.

5. Write Notion

Apply notion.md's write policy to every candidate, in this order:

  1. Rows to close: ticket statusCategory Done, or (no ticket) PR merged/closed → Status Done, closing log entry. Ticket-backed rows that fell out of scope → Done as "dropped", with the log entry.
  2. Existing rows: write the state the evidence supports: Status (Today included), Code state, PR Link, Due, Notes, Next step, Waiting on, Since, Last synced, Priority; append one Actions row per material event since the window start that is not already logged. On user-edited rows apply the anti-flip-flop rule: newer evidence wins and is named in Changes applied; otherwise the user's values stand and their Notes are folded in, not overwritten.
  3. New rows: create for new assignments to the user, new review requests, deploy-ready tickets not yet tracked, and anything else from step 3 where the next move is the user's or they are waiting on someone. Apply the umbrella rule (three or more same-project, same-state tickets → one row).
  4. Proposals: only the two cases notion.md reserves (closing a ticketless, linkless row; a question the evidence cannot settle).

Rate limits (429) → wait retry_after, retry. Record every write for the Changes applied section.

Done when: every open row carries today's Last synced (in catchup, every row a feed raised), every new item has a row or a proposal, and the applied-writes list is complete.

6. Backlog sweep (sweep mode only)

Sweep assignee = currentUser() AND statusCategory != Done ORDER BY updated ASC to the last page. Fan out to subagents by project; every ticket gets a full read (comments and changelog), no cap. For each ticket not already handled in steps 3–5 decide: the user's move → new row or proposal; waiting on someone 7+ days → chase flag; untouched 30+ days → stale flag with a close / schedule / hand-off proposal. Then run the database-health checks from notion.md (Today unedited 5+ days, more than 3 Doing, Waiting without Waiting on, rows with no ticket and no link untouched 30+ days).

Done when: the sweep count equals the JQL total and every ticket has a tier.

7. Standup

Skipped in catchup. Build the standup per standup.md: Yesterday from the user's log, their Sync events, scripts/local-commits.sh, scripts/claude-sessions.sh and their own Slack messages over Covers since → today; Today from the Work database as step 5 left it; Blockers from Waiting rows. Write it to the Standups database (today's row, created or rewritten), with Planned set to the Today rows. Every daily and sweep run writes one, quiet days included.

Done when: today's Standups row has all three sections, Covers since and Planned are set, and any source that failed is noted for Not verified.

8. Brief

Compose the briefing per briefing.md: six sections in fixed order, proposals as to-do blocks in the proposal grammar, first line linking the standup. Write it to the Briefings database titled Daily briefing — 6 Oct 2026 or Weekly sweep — 6 Oct 2026 (today's real date; a same-day re-run updates that row), with every property set. Then set the standup's Briefing relation to it. Print the standup and the briefing in chat. Quiet run with nothing to report and nothing written → one line in chat, no briefing row.

In catchup: the catch-up shape from briefing.md, titled Catch-up — 6 Oct 2026 14:05 (its own row, Mode catchup, first line linking the morning briefing instead of a standup). Print the briefing in chat. Nothing arrived and nothing written → one line in chat, no row.

The last two lines of output are always STANDUP: <notion url> then BRIEFING: <notion url> (or BRIEFING: none on a quiet run). catchup and apply print only the BRIEFING: line. scripts/run.sh reads both for the notification.

Done when: the briefing row exists with all six sections and its properties, the two rows are linked, the chat copy matches, and both final lines are printed.

Apply mode

  1. Open the newest Briefings row (query in briefing.md). Collect every to-do block under Proposals that is ticked (- [x]).
  2. Parse each with the proposal grammar in briefing.md. A line that does not parse is reported, not guessed.
  3. Re-check the evidence is still true (the row still exists and is not Done; the ticket is still open). Apply each surviving change to Notion, log an Actions row where the grammar says so.
  4. Rewrite each applied to-do as - [x] ✅ Applied <date>: <original text> so a second apply skips it. Unticked proposals are left alone. Set the row's Open proposals to the unticked count.
  5. Print what was applied, what was skipped and why. Final line BRIEFING: <same row url>; no standup.

Interactive use: when the user is present and the briefing has unticked proposals, offer them as a multi-select instead of making them tick boxes.

Common mistakes

  • Verifying only rows with recent activity. Every open Work row is checked every run; that is the whole point.
  • Setting Code state from the Jira status name. Only the GitHub compare and PR state set it.
  • Leaving PR Link empty when the ladder found a PR for the key, or filling it from a release PR that only ships the branch.
  • Overwriting a row the user edited when nothing newer has happened, or leaving a row untouched when newer evidence says it moved. Timestamps decide.
  • Rewriting the user's Notes in the sync's words. Keep their sentence while it holds.
  • Setting Since on every write. It changes only when Status or the owner in Next step changes.
  • Logging an event that already has an Actions row (same Work row, same date, same text).
  • Two rows for one piece of work: a PR and its ticket are one item; three or more sibling tickets are one umbrella row.
  • Asking a question during an unattended run, or proposing what the evidence already settles. Write it and list it under Changes applied.
  • Any write to Jira, GitHub or Slack.
  • Guessing the weekday, or treating a single page of search results as the whole set.
  • Counting a Jira or GitHub app DM as a Slack ask, or treating a Slack ask as answered because the user reacted to it.
  • A person's name or ID in a Slack query or a subagent prompt. to:me and from:me are the only identity filters.
  • Stopping, or asking for consent, because the Slack tools are missing. Absent tools are a Not verified line.
  • Building Yesterday from the sync window instead of Covers since → today, or from commits alone when the user's own log says it better.
  • Ticket keys, PR numbers or implementation detail in a standup's spoken line. They go on the grey refs line under it.
  • Setting a Work row's Status because the standup suggests it. The standup lists; Status follows step 5's rules.
  • Re-verifying every open row in a catch-up, writing a standup from one, or letting a catch-up overwrite the morning briefing row.
  • Repeating the morning briefing's Needs you in a catch-up when nothing about those items changed.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.