--- name: project-sync description: Sync a project timeline using subagents for parallelism. Splits work by week and datasource to stay within context limits. Handles both first-time and incremental syncs. disable-model-invocation: true argument-hint: [project-name] --- # Project Sync **When to use:** Keep a project timeline up to date. Works whether the project has been synced before or not. **Precondition:** `projects/$0/datasources.md` must exist. If it doesn't, run `/project-init $0` first. ## Architecture: Coordinator + Subagents This skill is designed for **subagent execution** to stay within context limits. The main agent acts as a **coordinator** that delegates data-intensive work to subagents. ``` Coordinator ├── Phase 1: Gather (parallel subagents, one per datasource) │ ├── Subagent: Zulip → writes tmp/$0-sync/zulip.md │ ├── Subagent: Git → writes tmp/$0-sync/git.md │ └── Subagent: Meetings → writes tmp/$0-sync/meetings.md │ ├── Phase 2: Synthesize (parallel subagents, one per week) │ ├── Subagent: Week 1 → writes timeline/{year-month}/week-{n}.md │ ├── Subagent: Week 2 → writes timeline/{year-month}/week-{n}.md │ └── ... │ └── Phase 3: Finalize (coordinator directly) ├── timeline/index.md (add links to new weeks) ├── project.md (update living document) └── sync-state.md (update sync status) ``` --- ## Coordinator Steps ### Step 1: Determine Sync Range Check whether `projects/$0/sync-state.md` exists. **Case A — First sync (no sync-state.md):** Default range is **last 12 months through today**. If the user provided explicit dates as extra arguments (`$1`, `$2`), use those instead. **Case B — Incremental sync (sync-state.md exists):** Read `last_sync_date` from `projects/$0/sync-state.md`. Range is `last_sync_date` to today. ### Step 2: Read Datasources Read `projects/$0/datasources.md` to determine: - Zulip stream IDs and search terms - Git repository URL - Meeting room names - Entity types to prioritize ### Step 3: Prepare Scratch Directory ```bash mkdir -p tmp/$0-sync ``` This directory holds intermediate outputs from Phase 1 subagents. It is ephemeral — delete it after the sync completes. ### Step 4: Compute Week Boundaries Split the sync range into ISO calendar weeks (Monday–Sunday). Produce a list of `(week_number, week_start, week_end, year_month)` tuples. This list drives Phase 2. --- ## Phase 1: Gather Data (parallel subagents) Launch **one subagent per datasource**, all in parallel. Each subagent covers the **full sync range** and writes its output to a scratch file. The output must be organized by week so Phase 2 subagents can consume it. ### Subagent: Zulip **Input:** Sync range, PRIMARY stream IDs and search terms from datasources.md. **Important:** `threaded_conversation` entities only contain the **last 50 messages** in a topic. To get complete message history for a week, you must query `conversation_message` entities. **Task:** Two-step process for each PRIMARY stream: **Step 1:** List all thread IDs in the stream using `id_prefix`: ``` GET /api/v1/query entity_types=threaded_conversation connector_ids=zulip id_prefix=zulip:stream:{stream_id} limit=100 offset=0 ``` This returns all thread entities (e.g., `zulip:stream:155:topic_name`). Save these IDs. **Step 2:** For each week in the sync range, query messages from each thread: ``` GET /api/v1/query entity_types=conversation_message connector_ids=zulip parent_id={thread_id} # e.g., zulip:stream:155:standalone date_from={week_start} date_to={week_end} limit=100 offset=0 ``` Paginate through all messages for each thread/week combination. **Output:** Write `tmp/$0-sync/zulip.md` with results grouped by week: ```markdown ## Week {n} ({week_start} to {week_end}) ### Stream: {stream_name} - **Topic:** {topic} ({date}, {message_count} messages, {participant_count} participants) {brief summary or key quote} ``` ### Subagent: Git **Input:** Sync range, git repository URL from datasources.md. **Task:** **Important:** Git commands may fail due to gitconfig permission issues. Use a temporary HOME directory: ```bash # Set temporary HOME to avoid gitconfig permission issues export HOME=$(pwd)/.tmp-home mkdir -p ./tmp # Clone if needed, pull if exists if [ -d ./tmp/$0-clone ]; then export HOME=$(pwd)/.tmp-home && cd ./tmp/$0-clone && git pull else export HOME=$(pwd)/.tmp-home && git clone --depth 500 {url} ./tmp/$0-clone cd ./tmp/$0-clone fi # Get commits in the date range export HOME=$(pwd)/.tmp-home && git log --since="{range_start}" --until="{range_end}" --format="%H|%an|%ae|%ad|%s" --date=short # Get contributor statistics export HOME=$(pwd)/.tmp-home && git log --since="{range_start}" --until="{range_end}" --format="%an" | sort | uniq -c | sort -rn ``` **Output:** Write `tmp/$0-sync/git.md` with results grouped by week: ```markdown ## Week {n} ({week_start} to {week_end}) **Commits:** {count} **Contributors:** {name} ({count}), {name} ({count}) ### Key Commits - `{short_hash}` {subject} — {author} ({date}) ``` ### Subagent: Meetings **Input:** Sync range, meeting room names from datasources.md. **Task:** For each PRIMARY room, query meetings and run semantic search: ``` GET /api/v1/query entity_types=meeting date_from={range_start} date_to={range_end} room_name={room-name} limit=100 POST /api/v1/search search_text={project-name} entity_types=["meeting"] date_from={range_start} date_to={range_end} limit=50 ``` **Output:** Write `tmp/$0-sync/meetings.md` with results grouped by week: ```markdown ## Week {n} ({week_start} to {week_end}) ### Meeting: {title} ({date}, {room}) **Participants:** {names} **Summary:** {brief summary} **Key points:** - {point} ``` --- ## Phase 2: Synthesize Week Files (parallel subagents) After all Phase 1 subagents complete, launch **one subagent per week**, all in parallel. Each produces a single week file. ### Subagent: Week {n} **Input:** The relevant `## Week {n}` sections extracted from each of: - `tmp/$0-sync/zulip.md` - `tmp/$0-sync/git.md` - `tmp/$0-sync/meetings.md` Pass only the sections for this specific week — do NOT pass the full files. **Task:** Merge and analyze the data from all three sources. Categorize into: 1. **Key Decisions** — Technology migrations, architecture changes, vendor switches, security incidents, strategic pivots 2. **Technical Work** — Feature implementations, bug fixes, infrastructure changes 3. **Team Activity** — Core vs. occasional contributors, role changes 4. **Blockers** — Issues, delays, dependencies 5. **Deadline Discussions** — Target dates, commitments, timeline changes **Milestones:** When documenting milestones, capture BOTH: - **WHAT** — The technical achievement (e.g., "PostgreSQL migration") - **WHY** — The business objective (e.g., "to improve query performance from 107ms to 27ms and enable concurrent access for scaling") Search for business objectives in: meeting discussions about roadmap, Zulip threads about planning, PR descriptions, release notes, and any "why are we doing this" conversations. **Deadlines & Timeline Changes:** Search all data sources for: - **Explicit deadlines**: "deadline is", "due by", "target date", "ship by X", "launch date" - **ETAs and estimates**: "ETA", "expected by", "should be done" - **Changes**: "pushed back", "extended", "delayed", "moved up", "ahead of schedule", "slipped" - **Commitments**: Agreements on when something will be delivered - **Uncertainty**: "not sure when", "TBD", "need to figure out timeline" For each deadline discussion found, record: - What deliverable/milestone is being discussed - The date mentioned (if any) - Whether it's a new commitment, change, or removal - The source (which thread/meeting/commit) - Any context about why the timeline changed **Skip unless meaningful:** Routine check-ins, minor documentation updates, social chat. **Output:** Write `projects/$0/timeline/{year-month}/week-{n}.md` using the week file template from [project-history](../project-history/SKILL.md). Also return a **3-5 line summary** to the coordinator for use in Phase 3. Create the month directory first if needed: `mkdir -p projects/$0/timeline/{year-month}` --- ## Phase 3: Finalize (coordinator directly) The coordinator collects the summaries returned by all Phase 2 subagents. These summaries are small enough to fit in the coordinator's context. ### Step 5: Update Timeline Index Add links to new week files in `projects/$0/timeline/index.md`. Append entries under the appropriate year/quarter sections. Update milestones if any were reached. ### Step 6: Update Project Dashboard (project.md) **File:** `projects/$0/project.md` This is the **living document** — update it with current status from the week summaries: **Update these sections:** 1. **This Week's Focus** - What the team is actively working on now 2. **Last Week's Focus** - What was completed in the most recent week 3. **Team** - Current contributors and their focus areas 4. **Milestones** - Update status and add new ones with business objectives 5. **Recent Decisions** - Key decisions from the last 2-3 weeks 6. **Deadline History** - Track timeline discussions, commitments, and changes **Deadline Tracking:** - Scan all week summaries for deadline-related discussions - Add new entries to the "Timeline Evolution" table showing changes - Update "Current Commitments" with latest target dates - Note when deadlines are mentioned without specific dates (uncertainty) - Capture the reasoning behind timeline changes when available **Deadline History Format:** ```markdown ## Deadline History ### Current Commitments | Deliverable | Current Target | Source | Confidence | |-------------|---------------|--------|------------| | Feature X | Mar 15, 2026 | Sprint planning meeting | High | | Beta release | Q2 2026 | Roadmap discussion | Medium | ### Timeline Evolution | Date | Change | Previous | New | Reason | Source | |------|--------|----------|-----|--------|--------| | Feb 10 | Extended | Feb 28 | Mar 15 | Additional testing needed | #dev channel | | Jan 15 | Committed | - | Feb 28 | Initial sprint commitment | Sprint kickoff | ``` **Milestone Format:** ```markdown ### In Progress 🔄 | Milestone | Target | Business Objective | |-----------|--------|-------------------| | Standalone deployment | Feb 2026 | Enable non-developers to self-host without complex setup | ### Recently Completed ✅ | Milestone | Date | Business Objective | |-----------|------|-------------------| | PostgreSQL migration | Mar 2025 | Improve performance (107ms→27ms) and enable scaling | ### Lost in Sight / Paused ⏸️ | Milestone | Status | Reason | |-----------|--------|--------| | Feature X | Paused | Resources reallocated to higher priority | ``` **Note:** Milestones in this company change frequently — update status (in progress/done/paused) as needed. ### Step 7: Update Sync State Create or update `projects/$0/sync-state.md`: **First sync (Case A):** ```markdown # Sync State status: synced created_at: {today's date} last_sync_date: {today's date} initial_history_from: {range_start} initial_history_to: {range_end} last_incremental_sync: {today's date} ``` **Incremental sync (Case B):** ```markdown # Sync State status: synced created_at: {original value} last_sync_date: {today's date} initial_history_from: {original value} initial_history_to: {original value} last_incremental_sync: {today's date} ``` ### Step 8: Cleanup ```bash rm -rf tmp/$0-sync ``` ### Step 9: Summary Report Output a brief summary: ```markdown ## Sync Summary: {Date} ### Period Covered {range_start} to {range_end} ### Key Changes 1. Decision: {brief description} 2. Feature: {what was built} 3. Team: {who joined/left} 4. Timeline: {deadline changes or commitments made} ### Metrics - {n} new commits - {n} active contributors - {n} weeks analyzed - {n} new Zulip threads - {n} meetings recorded ### Current Status [Status description] ``` --- ## Key Rules - **Link to sources**: Always reference commit hashes, PR numbers, Zulip topic names, meeting dates - **Be explicit about exclusions**: Document what you're NOT analyzing and why - **Write once**: Week files are historical records — don't modify existing ones, only create new ones - **Paginate all queries**: Always loop through all pages of results - **Distinguish contributor types**: Core (regular activity) vs. occasional (sporadic) - **Subagent isolation**: Each subagent should be self-contained. Pass only the data it needs — never the full scratch files - **Fail gracefully**: If a datasource subagent fails (e.g., git clone errors, API down), the coordinator should continue with available data and note the gap in the summary