diff --git a/.claude/drafts/TEMPLATE.md b/.claude/drafts/TEMPLATE.md new file mode 100644 index 00000000..57852d0d --- /dev/null +++ b/.claude/drafts/TEMPLATE.md @@ -0,0 +1,44 @@ +# [Feature/Change Title] + +## Type + + + +## Priority + + + +## Linear Tickets + + + +- TRUNK-XXXXX + +## What Changed + + + +## GitHub PRs + + + +## Context Links + + + +## Target Docs + + + +## Context + + diff --git a/.claude/skills/write-docs/OUTPUTS.md b/.claude/skills/write-docs/OUTPUTS.md new file mode 100644 index 00000000..b6e24267 --- /dev/null +++ b/.claude/skills/write-docs/OUTPUTS.md @@ -0,0 +1,58 @@ +# Output Formats + +Reference for all outputs produced by the write-docs skill. + +## Contents + +- [PR body format](#pr-body-format) +- [Slack post format](#slack-post-format) +- [Report card format](#report-card-format) + +## PR Body Format + +PR title: `[TRUNK-XXXXX] Short descriptive title` (prefix with Linear ticket ID if one exists). + +PR body sections: +- **Summary** — bullet list of changes +- **Linear tickets** — clickable links to all related tickets +- **Context links** — all Slack, Slite, Loom links from the notes +- **Files changed** — list of files created/modified +- **Open questions** — things that could not be confirmed from available context +- **Test plan** — checklist for reviewer (e.g., "check GitBook preview", "verify code example works") + +## Slack Post Format + +Write to `.claude/tmp//slack.md`. Must be directly copy-pasteable into Slack. + +**MUST use Slack mrkdwn syntax, NOT Markdown:** +- Bold: `*text*` (single asterisks, not double) +- Links: `` +- Bullets: use the `*` character on a new line (Slack list style) +- No Markdown headers (`##`), links (`[text](url)`), or bold (`**text**`) + +Template: +``` +*[Feature Name] — docs update ready for review* + +[1-2 sentence summary of what changed in the docs.] + +* PR: +* Linear: + +*Open questions for the team:* +* [list any items needing eng confirmation] +``` + +## Report Card Format + +Append an HTML card to `.claude/tmp/report.html`. If the file does not exist, create it with basic HTML styling. + +Each card includes: +- PR link +- Linear link +- Change type badge +- Changes summary +- Context links +- Related tickets +- Review focus areas +- Open questions diff --git a/.claude/skills/write-docs/OVERLAP-CHECK.md b/.claude/skills/write-docs/OVERLAP-CHECK.md new file mode 100644 index 00000000..d361c17a --- /dev/null +++ b/.claude/skills/write-docs/OVERLAP-CHECK.md @@ -0,0 +1,51 @@ +# Duplicate & Overlap Check + +Run these checks before starting any work. Stop and ask the user if any match is found. + +## Step 1: Check for existing PRs/branches from this draft + +1. Derive the expected branch topic from the draft filename (e.g., `flag-as-flaky.md` -> `flag-as-flaky`). Get the username prefix from `git config user.name` (kebab-cased). + +2. Search for open PRs matching the branch: + ```bash + gh pr list --repo trunk-io/docs --state open --head "/" --json number,title,url,headRefName + ``` + Also search by topic keyword: + ```bash + gh pr list --repo trunk-io/docs --state open --json number,title,url,headRefName | jq '.[] | select(.headRefName | contains(""))' + ``` + +3. Check local branches: + ```bash + git branch --list "**" + ``` + +4. **If a match is found**: Show the user the existing PR/branch and ask: + - (a) Update the existing PR + - (b) Close it and start fresh + - (c) Skip this draft + + Do NOT proceed until the user responds. + +## Step 2: Check for overlapping PRs from other authors + +1. Read the draft to identify target docs files/product area. + +2. List all open PRs: + ```bash + gh pr list --repo trunk-io/docs --state open --json number,title,headRefName,url --limit 50 + ``` + +3. For any PR that looks related (by title or branch name matching the same product area), check file overlap: + ```bash + gh pr view --repo trunk-io/docs --json files --jq '[.files[].path]' + ``` + +4. **If overlapping PRs are found**: Show the user the overlapping PR and affected files, then ask: + - (a) Proceed anyway (changes will likely conflict) + - (b) Wait for that PR to merge first + - (c) Skip this draft + + Do NOT proceed until the user responds. + +5. **If no overlaps found**: Continue to Phase 1. diff --git a/.claude/skills/write-docs/README.md b/.claude/skills/write-docs/README.md new file mode 100644 index 00000000..4dfdb2d6 --- /dev/null +++ b/.claude/skills/write-docs/README.md @@ -0,0 +1,278 @@ +# write-docs skill + +End-to-end documentation pipeline: raw notes -> reviewed docs PR with Linear tracking. + +Invoked as `/write-docs `. + +## Directory Structure + +``` +write-docs/ +├── SKILL.md # Main instructions (~130 lines, loaded when skill triggers) +├── OVERLAP-CHECK.md # Detailed dupe/overlap check procedure (loaded in Phase 0) +├── OUTPUTS.md # PR body, Slack post, report format specs (loaded in Phases 4-6) +└── README.md # This file (human reference only) +``` + +## How It Works + +The skill uses progressive disclosure: Claude loads SKILL.md when triggered, then reads OVERLAP-CHECK.md and OUTPUTS.md only when it reaches the relevant phase. This keeps the context window lean. + +### Pipeline + +``` +Phase 0 Duplicate & overlap check Stops if a PR/branch already covers this draft +Phase 1 Parse input Read notes file, extract tickets, PRs, context links +Phase 2 Research Linear tickets, Slite PRDs, Slack channels, + published docs, trunk2 PR diffs, gap analysis +Phase 2.5 Sources Write audit trail to .claude/tmp//sources.md +Phase 3 Draft Edit existing pages or create new docs files +Phase 4 Branch & PR Stash → branch → commit → push → gh pr create +Phase 5 Linear Create/update ticket, attach links, add relations +Phase 6 Stage Write slack.md, append to report.html +Phase 7 Clean up Restore original branch and stashed changes +``` + +### Research Sources (Phase 2) + +The skill cross-references five sources to build context before writing anything: + +| Source | What it finds | MCP Server | +| ------------------ | ---------------------------------------------------------------------------------------- | --------------------- | +| **Linear** | Ticket descriptions, status, assignees, related tickets | `claude.ai Linear` | +| **Slite** | PRDs, specs, roadmap items, knowledge base articles | `claude.ai Trunk Slite` | +| **Slack** | Team discussions, changelogs, feature context from `#team-flaky-tests`, `#team-merge-queue` | `claude.ai Slack` | +| **Published docs** | Existing documentation pages, hierarchy from `summary.md` | `claude.ai trunk docs` | +| **GitHub** | trunk2 PR diffs, code changes, implementation details | `gh` CLI | + +### Inputs + +| Input type | Example | What happens | +| ----------------- | --------------------------------- | --------------------------------------------------------------- | +| Notes file | `.claude/drafts/flag-as-flaky.md` | Primary mode. Reads file, extracts metadata, researches, writes | +| trunk2 PR numbers | `3187 3177` | Reads PR details via `gh`, extracts Linear IDs | +| Linear ticket IDs | `TRUNK-17633` | Looks up ticket, finds related PRs and context | +| Deploy tag | `v126` | Documents features shipped in a specific release | + +Notes files follow the template at `.claude/drafts/TEMPLATE.md`. + +### Outputs + +**Committed (the PR):** + +- Branch: `/` +- PR title: `[TRUNK-XXXXX] Short descriptive title` +- PR body: summary, Linear links, context links, files changed, open questions, test plan + +**Staged (gitignored, under `.claude/tmp//`):** + +- `sources.md` — audit trail for reviewers (every source consulted) +- `slack.md` — copy-pasteable Slack announcement (uses Slack mrkdwn, not Markdown) + +**Cumulative (`.claude/tmp/report.html`):** + +- HTML card appended per run — PR link, Linear link, changes summary, open questions + +**Linear:** + +- Ticket created/updated in Docs Maintenance project with `docs` label +- Context links attached (Slack, Slite, Loom, etc.) +- Related engineering tickets linked via `relatedTo` +- Status set to "In Review" + +### Prerequisites + +The skill requires these MCP servers to be connected. Verify with `claude mcp list`: + +- `claude.ai Slack` — for searching team channels +- `claude.ai Trunk Slite` — for PRDs and specs +- `claude.ai trunk docs` — for searching published docs +- `claude.ai Linear` — for ticket management +- GitHub via `gh` CLI (authenticated with access to `trunk-io/trunk2`) + +--- + +## Demo Script + +Walkthrough for demoing `/write-docs` at an all-hands or team meeting. Total runtime: ~5 minutes. + +### Pre-Demo Setup (10 min before) + +#### 1. Clean terminal state + +```bash +cd ~/TRUNK/docs +git checkout main +git pull origin main +git status # should be clean +``` + +#### 2. Verify no leftover demo artifacts + +```bash +git branch --list "*indefinite-monitor-muting*" +gh pr list --repo trunk-io/docs --state open --json number,title,headRefName | jq '.[] | select(.headRefName | contains("indefinite-monitor-muting"))' + +# If either returns results, clean up: +# gh pr close --repo trunk-io/docs --delete-branch +# git branch -D sam-gutentag/indefinite-monitor-muting +``` + +#### 3. Verify draft and clear previous outputs + +```bash +cat .claude/drafts/indefinite-monitor-muting.md +rm -rf .claude/tmp/indefinite-monitor-muting/ +``` + +#### 4. Verify MCP servers + +```bash +claude mcp list +``` + +All five should show connected (see [Prerequisites](#prerequisites) above). + +#### 5. Start Claude Code + +```bash +claude +``` + +Wait for it to load. Verify `/write-docs` is recognized. + +#### 6. Terminal setup + +- Font size: 18-20pt for readability +- Terminal width: full screen, max 120 chars +- Dark theme for projector visibility + +### The Demo + +#### ACT 1: The Problem (30 seconds) + +**[Speaking to audience, terminal visible but idle]** + +> "Quick show of hands — who's had to write documentation for a feature someone else built? Yeah. It's not the writing that's painful, it's the context-gathering. You're reading Slack threads, digging through PRs, searching Linear, figuring out which docs pages need updating. Then you do the actual writing. Then you create a branch, open a PR, update the ticket, post in Slack. That's 30 minutes for something that should take 5." + +> "We built a Claude Code skill that does all of that from a single command. Let me show you." + +#### ACT 2: Show the Input (30 seconds) + +**[In Claude Code, type:]** + +``` +cat .claude/drafts/indefinite-monitor-muting.md +``` + +**[Let the file scroll. Point out key sections:]** + +> "This is a notes file — it's what an engineer or PM drops into our drafts folder. It has the feature name, links to the PRs that shipped it, and which docs pages need updating. It's rough and that's fine — it's input, not output." + +> "Notice there's no Linear ticket yet, no branch, no PR. Just notes." + +#### ACT 3: Run the Skill (2-3 minutes) + +**[Type the command:]** + +``` +/write-docs .claude/drafts/indefinite-monitor-muting.md +``` + +**[Narrate each phase as it runs. Don't rush — let the audience watch the tool calls.]** + +When you see `gh pr list` calls: +> "Phase zero — it's checking whether someone already opened a PR for this, or if another PR touches the same docs files." + +When you see `mcp__claude_ai_Linear` calls: +> "Now it's researching. Starts with Linear to get ticket context..." + +When you see Slite or Slack MCP calls: +> "It's searching our Slite knowledge base for PRDs and checking the #team-flaky-tests Slack channel for recent discussion. This is context that used to take 10 minutes of manual digging." + +When you see `gh pr view` or `gh pr diff` calls: +> "Reading the trunk2 PR to see what code actually shipped." + +When you see a file being written to `.claude/tmp/`: +> "That's the sources file — an audit trail so reviewers can trace any claim back to its source." + +When you see `Edit` tool calls on docs files: +> "Now it's writing the actual docs. It read the existing pages first to match our tone and structure." + +When you see `git` commands: +> "Creating a branch, committing, pushing..." + +When you see `gh pr create`: +> "And there's the PR." + +When you see Linear calls: +> "Creating a Linear ticket, attaching the PR link, context URLs, and linking related engineering tickets." + +#### ACT 4: Show the Outputs (1 minute) + +**[Claude will output a summary with links. Click through each one:]** + +**GitHub PR** — open in browser: +> "The title has the Linear ticket ID. The body has open questions — things it couldn't confirm from the available context. It flags what needs human verification instead of guessing." + +**Linear ticket** — open in browser: +> "Docs Maintenance project, assigned to me, status In Review. It attached the PR link, the Slack threads it found, and any Slite docs it consulted." + +**[Show staged outputs:]** + +``` +cat .claude/tmp/indefinite-monitor-muting/slack.md +cat .claude/tmp/indefinite-monitor-muting/sources.md +``` + +> "A copy-pasteable Slack post and a full sources audit trail." + +#### ACT 5: Wrap Up (30 seconds) + +> "From one command and a rough notes file: a docs PR, a Linear ticket, an audit trail, and a team notification. About 3 minutes." + +> "The skill searches five systems — Linear, Slite, Slack, our published docs, and GitHub PRs — to build context before writing a single line. Every PR still gets human review." + +### Q&A + +**"What if the docs it writes are wrong?"** +> "Every PR gets human review. The skill flags open questions explicitly. It's doing the 80%, a human does the last 20%." + +**"Can this work for other repos?"** +> "The skill is specific to our docs workflow, but the pattern is portable. You write a SKILL.md describing the pipeline and Claude Code follows it." + +**"How long did it take to build?"** +> "About 130 lines of instructions plus two reference files. The iteration was the slow part — maybe 2-3 sessions." + +**"What if it creates a PR that conflicts with someone else's work?"** +> "Phase 0 catches that. It checks every open PR for file-level overlap before doing any work." + +**"Does it handle new pages or just updates?"** +> "Both. New pages get created and added to summary.md. Updates edit existing files in place." + +**"How does it know what's in Slite and Slack?"** +> "We connected them as MCP servers — same protocol as Linear. The skill searches them during research, and knows to check #team-flaky-tests and #team-merge-queue for product context." + +### Post-Demo Cleanup + +```bash +gh pr close --repo trunk-io/docs --delete-branch +git checkout main +git branch -D sam-gutentag/indefinite-monitor-muting 2>/dev/null +rm -rf .claude/tmp/indefinite-monitor-muting/ +``` + +### Dry Run Checklist + +Do a full dry run the day before. Clean up everything so the live demo starts fresh. + +- [ ] Draft file exists at `.claude/drafts/indefinite-monitor-muting.md` +- [ ] No existing branch `sam-gutentag/indefinite-monitor-muting` +- [ ] No existing PR for indefinite-monitor-muting +- [ ] No existing `.claude/tmp/indefinite-monitor-muting/` directory +- [ ] Claude Code starts cleanly and recognizes the skill +- [ ] MCP servers are responding (Linear, GitBook, Slack, Slite) +- [ ] Terminal font size is readable from the back of the room +- [ ] You've timed the run — should be 2-4 minutes +- [ ] You know where to find the PR and Linear links in the output +- [ ] Linear "Docs Maintenance" project view is open in a browser tab diff --git a/.claude/skills/write-docs/SKILL.md b/.claude/skills/write-docs/SKILL.md new file mode 100644 index 00000000..b558e428 --- /dev/null +++ b/.claude/skills/write-docs/SKILL.md @@ -0,0 +1,131 @@ +--- +name: write-docs +description: Process notes, Slack threads, Slite docs, or trunk2 deploy context into documentation changes. Creates a branch, edits docs, opens a PR, and updates Linear. Use when given a notes file from .claude/drafts/, trunk2 PR numbers, Linear ticket IDs, a deploy tag, Slite doc links, or when the user says "write docs", "document this", or "process drafts". +allowed-tools: Bash(git *), Bash(gh pr *), Bash(gh issue *), Bash(gh api *), Read, Write, Edit, Glob, Grep, mcp__claude_ai_Linear__get_issue, mcp__claude_ai_Linear__list_issues, mcp__claude_ai_Linear__list_projects, mcp__claude_ai_Linear__save_issue, mcp__claude_ai_Linear__save_comment, mcp__claude_ai_Linear__create_attachment, mcp__claude_ai_trunk_docs__searchDocumentation, mcp__claude_ai_Trunk_Slite__*, mcp__claude_ai_Slack__*, WebFetch +--- + +# Writing Docs + +Turn raw notes, Slack pastes, and PR references into reviewed docs PRs with full Linear tracking. + +## Contents + +- [Inputs](#inputs) +- [Products](#products) +- [Workflow](#workflow) +- [Guidelines](#guidelines) +- [Batch processing](#batch-processing) + +## Inputs + +The user provides any combination of: +- **Notes file** (e.g., `.claude/drafts/my-feature.md`) — primary input. Template: `.claude/drafts/TEMPLATE.md` +- **trunk2 PR numbers** — PRs from `trunk-io/trunk2` +- **Linear ticket IDs** — `TRUNK-NNNNN` references +- **Deploy tag** (e.g., `v126`) — features shipped in a release +- **Slite doc links** — PRDs, specs, or knowledge base articles from Slite +- **Context links** — Slack threads, Loom videos, Google Docs, etc. +- **Specific docs page** — if the user knows what needs changing + +## Products + +Docs are organized by product area: +- **Merge Queue** — `/merge-queue/` +- **Flaky Tests** — `/flaky-tests/` +- **CI Autopilot** — `/ci-autopilot/` +- **Code Quality** — `/code-quality/` +- **Setup & Administration** — `/setup-and-administration/` + +## Workflow + +Copy this checklist and track progress: + +``` +Progress: +- [ ] Phase 0: Duplicate & overlap check +- [ ] Phase 1: Parse input +- [ ] Phase 2: Research (Linear, Slite, Slack, docs, PRs) +- [ ] Phase 2.5: Write sources audit file +- [ ] Phase 3: Draft documentation +- [ ] Phase 4: Branch, commit, PR +- [ ] Phase 5: Update Linear +- [ ] Phase 6: Stage outputs (Slack post, report) +- [ ] Phase 7: Clean up and summarize +``` + +### Phase 0: Duplicate & Overlap Check + +Before doing any work, verify no existing PR already covers this draft. See [OVERLAP-CHECK.md](OVERLAP-CHECK.md) for the detailed check procedure. + +If a match or overlap is found, stop and ask the user how to proceed before continuing. + +### Phase 1: Parse and Understand + +1. If a notes file was provided, read it and extract: feature name, Linear ticket IDs, GitHub PR URLs, context links, product area, change type, and key details. +2. If trunk2 PR numbers or a deploy tag were provided instead, use `gh pr view --repo trunk-io/trunk2` to get details and extract Linear ticket IDs. + +### Phase 2: Research + +**Code is law.** Actual source code and PR diffs are the authoritative source of truth. Slite specs, PRDs, Slack threads, and other planning docs provide context, intent, and examples — but when they conflict with what the code does, the code wins. Only document what is actually implemented. + +3. **Linear tickets**: Use `mcp__claude_ai_Linear__get_issue` for each ticket ID. Search by feature name for related engineering tickets. +4. **Slite docs**: Search Slite for PRDs, specs, roadmap items, and knowledge base articles related to the feature. Use feature name and product area as search terms. Retrieve relevant docs for product intent, requirements, and decisions. +5. **Slack channels**: Search relevant Slack channels for recent discussion, changelogs, and context: + - `#team-flaky-tests` — Flaky Tests product discussions + - `#team-merge-queue` — Merge Queue product discussions + - Search by feature name, ticket ID, or key terms from the notes +6. **Existing docs**: Use `mcp__claude_ai_trunk_docs__searchDocumentation`, Glob, and Grep. Read `summary.md` for the docs hierarchy. +7. **trunk2 PR diffs** (if available): `gh pr diff --repo trunk-io/trunk2 --name-only`, then read key files. When possible, also read the current source on `main` via `gh api` to confirm the latest state. +8. **Gap analysis**: Compare existing docs vs. what the code implements. Cross-reference planning docs (Slite, Slack) against code to identify discrepancies — features described in specs but not yet implemented should be flagged as open questions, not documented as existing functionality. + +### Phase 2.5: Generate Sources File + +9. Write `.claude/tmp//sources.md` with all Linear tickets, GitHub PRs, Slite docs, Slack threads, existing docs, code references, and context links found during research. This is the reviewer audit trail. Must include: + - A **"Code-Confirmed Details"** section listing metric names, endpoint paths, auth mechanisms, etc. as they exist in the actual codebase + - A **"Differences: Code vs. Planning Docs"** table highlighting any discrepancies between what planning docs describe and what the code implements + - An **"Open Questions"** section for anything that could not be confirmed from code + +### Phase 3: Draft Documentation + +8. Write or edit documentation: + - **Match tone and structure** of existing Trunk docs — read nearby files first + - **New pages**: write full content; **Updates**: edit in place; **Explainers**: add to relevant existing page + - Update `summary.md` if adding new pages + - Lead with user benefit, not implementation details + - Use present tense, include practical examples + - Don't mention internal systems (ClickHouse, Prisma, SST, Lambda) + +### Phase 4: Branch, Commit, and PR + +9. **Branch**: From `main`. Name: `/` (username from `git config user.name`, kebab-cased). Stash unrelated changes first. +10. **Commit**: Stage changed files. Include `Co-Authored-By: Claude Opus 4.6 `. +11. **Push and PR**: `gh pr create` with structured body. See [OUTPUTS.md](OUTPUTS.md) for PR body format. + +### Phase 5: Update Linear + +12. Create or update the docs ticket — add PR link, context links, change summary. Set status to "In Review". If no ticket exists, create one in Trunk Engineering with `docs` label. +13. Attach all context links (Slack, Slite, Loom) as attachments with descriptive titles. +14. Add `relatedTo` relations for every related engineering ticket found during research. + +### Phase 6: Stage Outputs + +15. **Slack post**: Write to `.claude/tmp//slack.md`. See [OUTPUTS.md](OUTPUTS.md) for Slack formatting rules. +16. **Report**: Append an HTML card to `.claude/tmp/report.html`. See [OUTPUTS.md](OUTPUTS.md) for report format. + +### Phase 7: Clean Up + +17. Return to original branch, restore stashed changes. +18. Show the user: branch name, PR link, Linear ticket link, files changed, open questions, staged output file paths. + +## Guidelines + +- **One notes file = one PR.** Flag multi-topic drafts and ask how to split. +- **Preserve the notes file** — never delete or modify it. +- **Ask before guessing** — list specific questions rather than making assumptions. +- **Always include full PR URLs** in Linear comments and descriptions. +- **Match existing style** — read adjacent docs before writing. +- **Prioritize accuracy** — flag inferred vs. confirmed items in open questions. + +## Batch Processing + +Process each notes file in `.claude/drafts/` one at a time. Each gets its own branch, PR, Linear ticket, and `.claude/tmp//` directory. The skill handles git stash/restore between runs. diff --git a/.gitignore b/.gitignore index b534937b..1ee334fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ # Mac .DS_Store /.idea/workspace.xml + +# Agent drafts (notes files are personal, template is committed) +.claude/drafts/*.md +!.claude/drafts/TEMPLATE.md + +# Agent outputs (local working files, all under tmp/) +.claude/tmp/ diff --git a/readme.md b/readme.md index c1ef8e52..2b0c0c78 100644 --- a/readme.md +++ b/readme.md @@ -6,6 +6,33 @@ This repository is the official repo for [docs.trunk.io][docs]. If you see any mistakes or any improvements that can be made, we'd love your contributions! +## Local Development + +This repo is synced with [GitBook](https://www.gitbook.com/) via Git Sync. Content pushed to `main` is automatically published to [docs.trunk.io][docs]. To preview changes before publishing: + +### Setup + +1. Push your feature branch to GitHub: + ```bash + git push -u origin your-branch-name + ``` +2. In the GitBook editor, create a **Change Request** linked to your branch. +3. GitBook will render your branch content in a preview, separate from the published docs. + +### Workflow + +``` +Edit locally → git push → GitBook auto-syncs branch → Preview in GitBook editor + ↓ + Review & iterate + ↓ + Merge PR on GitHub → publishes to docs.trunk.io +``` + +- Every push to your branch updates the GitBook preview automatically +- Edits made in the GitBook web editor push commits back to your branch +- Nothing goes live on docs.trunk.io until the branch merges to `main` + ## Contributing If you see any mistakes or any improvements that can be made, we'd love your contributions! Just fork the repo and open a PR with your changes. While you're browsing [docs.trunk.io][docs], you can get to the GitHub source for that page via the `...` menu → `Edit on GitHub`: