{"skill":{"slug":"pullstar-1on1","displayName":"Engineering manager 1-on-1 meeting brief generator","summary":"Generate a ready-to-use 1-on-1 brief for any engineer on your team — from their GitHub activity, in seconds. Spots patterns like high output but low review p...","description":"---\nname: skills\ndescription: Generate a ready-to-use 1-on-1 brief for any engineer on your team — from their GitHub activity, in seconds. Spots patterns like high output but low review participation, large PR sizes suggesting batching, and cross-repo collaboration signals.\nlicense: MIT\n---\n\n## Overview\n\nPullStar fetches GitHub activity for one engineer (PRs authored, reviews given), runs a **deterministic local scoring engine** across five dimensions, and prepares an LLM input payload. The **agent** then performs LLM inference and finalizes the brief.\n\n\n**Quickstart:** \n\n    run_brief.py --login steipete --pr-insights --days 7\n    Read llm_input_steipete.json, do the LLM inference, present the brief\n\n\n\n**Data Flow Summary:**\n\n| Step | What runs | External calls |\n|------|-----------|----------------|\n| Ingest | `run_brief.py` → `ingest.py` | GitHub API |\n| Score | `run_brief.py` → `score.py` | None |\n| Prepare | `run_brief.py` → `agent_prepare_1on1.py` | None |\n| **Agent inference** | **Agent calls LLM** | **LLM provider** |\n| Finalize | Agent runs `agent_finalize_1on1.py` | None |\n\n**⚠️ Important:** Steps 1–3 run locally. Only the LLM inference step (step 4) sends data to your AI provider.\n\n---\n\n## Requirements\n\n- Python 3.11+\n- Install dependencies: `pip install PyGithub python-dotenv requests`\n- A GitHub personal access token (see Security section below)\n\n---\n\n## Security & Privacy\n\n### Token Scope\n\n| Option | Where to create | Best for |\n|--------|----------------|----------|\n| Classic PAT (`repo` scope) | https://github.com/settings/tokens | Cross-user search, org-wide ingestion |\n| Fine-grained PAT | https://github.com/settings/personal-access-tokens | Your own repos only |\n\n> Fine-grained PATs cannot search across arbitrary users. Use a classic PAT for org-wide briefs.\n\nSet `GITHUB_ORG` to narrow search to one organization.\n\n### Token Resolution Order\n\nSecrets are resolved using layered lookup — first match wins:\n\n1. `--github-token` CLI flag (override/debug only — never logged)\n2. `GITHUB_TOKEN` environment variable\n3. `~/.pullstar/credentials` (key=value format)\n4. `.env` in the skill directory\n\n### Data Privacy by Mode\n\n**Default (no `--pr-insights`):**\n- Only aggregated statistics and scores sent to LLM\n- No raw PR text, comments, or review bodies included\n\n**PR Insights (`--pr-insights`):**\n- Bounded raw PR discussion text packaged into the LLM prompt\n- Bounded to 5 PRs, 3 reviews/comments each, 600 char limit per item\n- Review `llm_input_{login}.json` before inference if you have privacy concerns\n\n---\n\n## Configuration\n\n### `.env`\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `GITHUB_TOKEN` | Recommended | Classic PAT with `repo` scope. Omit for unauthenticated access (60 req/hr). |\n| `GITHUB_ORG` | No | Scope ingestion to one org. |\n\n---\n\n## Usage\n\n### Standard run\n\n```bash\npython run_brief.py --login jsmith\n```\n\n### With PR insights\n\n```bash\npython run_brief.py --login jsmith --pr-insights\n```\n\n### Common options\n\n```bash\npython run_brief.py --login jsmith --days 14          # wider lookback (default: 5)\npython run_brief.py --login jsmith --max-results 10   # faster on high-activity users (default: 20)\npython run_brief.py --login jsmith --api-mode rest    # force REST API (default: graphql)\n```\n\n### All options\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `--login` | required | Engineer GitHub login |\n| `--days` | `5` | Lookback window in days |\n| `--pr-insights` | off | Include PR review/comment context in LLM prompt |\n| `--max-results` | `20` | Max search results to iterate (lower = faster) |\n| `--api-mode` | `graphql` | `graphql` or `rest` |\n| `--output-dir` | `.pullstar` | Directory for all artifacts |\n| `--github-token` | — | Override/debug only. Prefer `.env`. |\n\n---\n\n## Agent Flow\n\n`run_brief.py` runs the deterministic pipeline (ingest → score → prepare) and then prints an explicit instruction block. The agent must complete the final two steps:\n\n```\n============================================================\nPIPELINE COMPLETE — AGENT ACTION REQUIRED\n============================================================\n\n  1. Read:   .pullstar/llm_input_jsmith.json\n  2. Extract the \"system\" and \"user\" fields\n  3. Call your LLM with those as the system prompt and user message\n  4. Write the response to .pullstar/llm_output_jsmith.json\n  5. Run:    python scripts/agent_finalize_1on1.py --login jsmith\n```\n\n---\n\n## Agent JSON Contract\n\n### Input (from `run_brief.py`)\n\nFile: `.pullstar/llm_input_{login}.json`\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `system` | string | System prompt with instructions |\n| `user` | string | User message with engineer data and scores |\n| `metadata` | object | Version, timestamps, total score, confidence |\n\n### Output (from agent)\n\nFile: `.pullstar/llm_output_{login}.json`\n\n```json\n{\n  \"version\":        \"1.0\",\n  \"engineer_login\": \"jsmith\",\n  \"brief\":          \"## Quick Summary\\n...\"\n}\n```\n\n**Requirements:**\n- Valid JSON\n- `brief` must be a non-empty markdown string\n- Plain text is also accepted — the full file content will be used as the brief\n\n---\n\n## Brief Output Format\n\nThe final brief (`output_{login}.json`) contains a markdown document with six sections:\n\n| Section | Content |\n|---------|---------|\n| **Quick Summary** | 2–3 sentences, lead with concrete numbers |\n| **Highlights** | 2–4 bullets, one data point each |\n| **Areas to Explore** | 2–3 open-ended questions for the 1-on-1 |\n| **Patterns Worth Noting** | 1–3 factual behavioral observations |\n| **Score Summary** | Markdown table — Dimension / Score / Confidence / Signal. Emoji encouraged in Confidence column. |\n| **Suggested Focus** | One paragraph on the most useful 1-on-1 theme |\n\nExample Score Summary table:\n\n| Dimension | Score | Confidence | Signal |\n|-----------|-------|------------|--------|\n| Velocity | 16/20 | ✅ High | 10 PRs merged, 3 active weeks |\n| PR Quality | 14/20 | ✅ High | Avg 320 lines, 2 large PRs flagged |\n| Review Participation | 8/20 | ⚠️ Medium | 3 reviews given in window |\n| Collaboration | 12/20 | ✅ High | 4 repos, 3 reviewers per PR avg |\n| Consistency | 10/20 | 🔴 Low | 1 of 3 weeks inactive |\n\n---\n\n## Artifacts\n\nAll artifacts are written to `.pullstar/` (gitignored, never committed).\n\n| File | Written by | Sent to AI? |\n|------|------------|-------------|\n| `ingest_{login}.json` | `ingest.py` | ❌ No |\n| `score_{login}.json` | `score.py` | ❌ No |\n| `llm_input_{login}.json` | `agent_prepare_1on1.py` | ✅ Yes |\n| `llm_output_{login}.json` | Agent | ❌ No |\n| `output_{login}.json` | `agent_finalize_1on1.py` | ❌ No |\n\n---\n\n## Troubleshooting\n\n**\"GitHub rejected the PR search query (422)\"**\nUse a classic PAT — fine-grained PATs cannot search across arbitrary users.\n\n**\"GitHub rate limit hit\"**\nAuthenticated: 5000 req/hr. Unauthenticated: 60 req/hr. Set `GITHUB_TOKEN`.\n\n**Slow ingestion on high-activity users**\nUse `--max-results 10` to cap iteration. Default is 20.\n\n**GraphQL errors**\nUse `--api-mode rest` to fall back to the legacy REST API.\n\n---\n\n## For Agent Developers\n\n### Subagent Best Practices (Don't Be a Nervous Parent)\n\nWhen using `sessions_spawn` for the LLM inference step:\n\n**✅ Do:**\n- Spawn once with the task to read `llm_input_{login}.json` and write `llm_output_{login}.json`\n- Trust the \"auto-announces on completion\" behavior — you'll get a completion event\n- Handle the result when the event arrives\n\n**❌ Don't:**\n- Poll `subagents list` in a tight loop waiting for completion\n- Spawn multiple subagents for the same task\n- Check status every few seconds — it's wasteful\n\n**Why:** Subagents are lightweight (no full OpenClaw context, isolated environment), but polling defeats the purpose of push-based completion. The system will tell you when it's done.\n\n**Recovery:** If a subagent fails, you can always generate the brief directly in the main session — the JSON contract is simple and documented above.\n\n---\n\n## License\n\nMIT — See source repository for full license text.\n","tags":{"latest":"1.0.2"},"stats":{"comments":0,"downloads":456,"installsAllTime":17,"installsCurrent":0,"stars":0,"versions":3},"createdAt":1778012429552,"updatedAt":1780346656712},"latestVersion":{"version":"1.0.2","createdAt":1780346656712,"changelog":"pullstar-1on1 v1.0.2\n\n- Switched to a new entry point: added run_brief.py for unified brief generation.\n- Added GitHub GraphQL mode as default, with REST fallback and --api-mode flag\n- Expanded documentation: added README.md with updated usage, config, and privacy details.\n- Clarified agent and LLM inference instructions for output workflow.\n- Updated dependencies list (requires 'requests').\n- Removed skill-card.md; see README.md and SKILL.md for all reference details.\n-skills/scripts/ingest.py now default to GitHub\nGraphQL API when a token is present, reducing API call count from ~200+ REST\ncalls per user to 2-4 GraphQL queries total. REST remains the automatic\nfallback when no GITHUB_TOKEN is found, preserving full backwards compatibility\nincluding unauthenticated access.","license":"MIT-0"},"metadata":null,"owner":{"handle":"jacksync","userId":"s17797mbhv0wkbd3wj9d1mynr185px38","displayName":"jacksync","image":"https://avatars.githubusercontent.com/u/9632126?v=4"},"moderation":null}