Files

386 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 (MondaySunday). 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