feat(commands): add GitHub repository project extraction to /expand (#437)

This commit is contained in:
Oscar Madera
2026-09-07 18:43:59 +02:00
committed by GitHub
parent 6176e6aaca
commit 6b07b13bd2
3 changed files with 75 additions and 2 deletions
+16 -2
View File
@@ -55,6 +55,7 @@ Look up the GitHub username from `01-candidate-profile.md`. If a GitHub URL or u
2. For each repository found: 2. For each repository found:
- Fetch the repository README - Fetch the repository README
- Note: name, description, primary language(s), topics/tags, any frameworks or libraries mentioned in the README - Note: name, description, primary language(s), topics/tags, any frameworks or libraries mentioned in the README
- If the repository represents an independent technical project (not an empty stub or uncustomized fork), extract a project summary (problem domain, tech stack, and demonstrable technical results) for consideration under Independent Projects
3. Also retrieve the full repository list if available (to catch unpinned repos) 3. Also retrieve the full repository list if available (to catch unpinned repos)
If no GitHub username or URL is found in the profile, skip this source and note it was skipped. If no GitHub username or URL is found in the profile, skip this source and note it was skipped.
@@ -108,19 +109,25 @@ After enriching all items, build a deduplicated competency map. Group findings i
**Domain Knowledge** (subject matter expertise: geophysics, ML, NLP, etc.) **Domain Knowledge** (subject matter expertise: geophysics, ML, NLP, etc.)
**Methods and Practices** (agile, version control, reproducibility, testing, etc.) **Methods and Practices** (agile, version control, reproducibility, testing, etc.)
**Soft / Behavioral** (leadership, communication, collaboration signals from references and project descriptions) **Soft / Behavioral** (leadership, communication, collaboration signals from references and project descriptions)
**Independent Projects & Portfolio** (distinct technical projects from GitHub with problem domain, tech stack, and key technical milestone)
For each competency, record: For each competency, record:
- The competency name - The competency name
- The source item it came from (e.g. "Coursera — Deep Learning Specialisation", "GitHub — repo-name", "Reference letter — Jens Jensen") - The source item it came from (e.g. "Coursera — Deep Learning Specialisation", "GitHub — repo-name", "Reference letter — Jens Jensen")
- Whether it came from direct lookup (A), inference (B), or both - Whether it came from direct lookup (A), inference (B), or both
For each project, record:
- Project name
- One-line summary: problem tackled, tech stack used, and verifiable outcome/impact
- Source (e.g. "GitHub — repo-name")
Remove anything already present in `01-candidate-profile.md` or `02-behavioral-profile.md`. Remove anything already present in `01-candidate-profile.md` or `02-behavioral-profile.md`.
--- ---
## Step 4: Present Grouped Summary ## Step 4: Present Grouped Summary
Present all new competencies for the user's review before writing anything. Format: Present all new competencies and project additions for the user's review before writing anything. Format:
``` ```
## /expand found [N] new competency signals across [M] sources ## /expand found [N] new competency signals across [M] sources
@@ -131,6 +138,11 @@ Source: [Course/cert name — Provider]
+ [Competency 2] + [Competency 2]
... ...
**PROJECTS & PORTFOLIO**
Source: [GitHub — repo-name]
+ [Project Name]: [Problem, stack, and outcome]
...
**GITHUB — [repo-name]** **GITHUB — [repo-name]**
Source: README + inferred from tech stack Source: README + inferred from tech stack
+ [Competency 1] + [Competency 1]
@@ -169,6 +181,7 @@ Wait for the user's response before writing anything.
Apply only the confirmed items. Use the Edit tool to add to the relevant sections of each file — do not rewrite entire files. Apply only the confirmed items. Use the Edit tool to add to the relevant sections of each file — do not rewrite entire files.
### Additions to `01-candidate-profile.md` ### Additions to `01-candidate-profile.md`
- Independent projects → append to the `## Independent Projects` section formatted as `- **[Project Name]**: [Description with stack and outcome] *(GitHub — repo-name)*`
- Technical skills (primary and secondary) → append to the Technical Skills section - Technical skills (primary and secondary) → append to the Technical Skills section
- Domain knowledge → append to the Domain Knowledge or Technical Skills section (match the existing structure) - Domain knowledge → append to the Domain Knowledge or Technical Skills section (match the existing structure)
- Methods and practices → append appropriately - Methods and practices → append appropriately
@@ -189,7 +202,7 @@ After writing, present:
## /expand Complete ## /expand Complete
### Added to 01-candidate-profile.md ### Added to 01-candidate-profile.md
[List each competency added, with source] [List each competency and independent project added, with source]
### Added to 02-behavioral-profile.md ### Added to 02-behavioral-profile.md
[List each behavioral signal added, with source] [List each behavioral signal added, with source]
@@ -214,3 +227,4 @@ After writing, present:
- **User confirms before writing.** The full competency map is shown and confirmed before a single file is touched. - **User confirms before writing.** The full competency map is shown and confirmed before a single file is touched.
- **Behavioral signals are labeled.** Anything inferred from tone, language, or indirect signals is marked as inferred so it is reviewed critically. - **Behavioral signals are labeled.** Anything inferred from tone, language, or indirect signals is marked as inferred so it is reviewed critically.
- **GitHub is fully scanned.** All public repositories are checked, not just pinned ones — unpinned repos often contain significant competency signals. - **GitHub is fully scanned.** All public repositories are checked, not just pinned ones — unpinned repos often contain significant competency signals.
- **Portfolio & projects grounded in code.** Independent projects added to the profile must reflect real projects found in public GitHub repositories — never fabricated project claims.
+6
View File
@@ -41,6 +41,12 @@ per-file diff commands.
### Added ### Added
- **`/expand` project and portfolio expansion** (`.claude/commands/expand.md`,
`tests/test_expand_command.py`) - expands candidate discovery
to technical projects from public GitHub repositories, extracting structured summaries
(problem domain, tech stack, key technical challenges, and verifiable outcomes) to
populate the `## Independent Projects` section of `01-candidate-profile.md`.
- **Stale sweep branch in `/outcome`** (`.claude/commands/outcome.md`, - **Stale sweep branch in `/outcome`** (`.claude/commands/outcome.md`,
`tests/test_outcome_stale.py`) - introduces `/outcome stale [N]` (and `/outcome sweep [N]`) `tests/test_outcome_stale.py`) - introduces `/outcome stale [N]` (and `/outcome sweep [N]`)
to batch-resolve open applications quiet for 60+ (or N) days. Displays a numbered summary to batch-resolve open applications quiet for 60+ (or N) days. Displays a numbered summary
+53
View File
@@ -0,0 +1,53 @@
"""Tests for the /expand command specification."""
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
EXPAND_COMMAND_FILE = REPO_ROOT / ".claude" / "commands" / "expand.md"
class ExpandCommandTests(unittest.TestCase):
def test_expand_command_file_exists(self):
self.assertTrue(EXPAND_COMMAND_FILE.exists(), "expand.md must exist under .claude/commands/")
def test_expand_command_file_starts_with_correct_header(self):
text = EXPAND_COMMAND_FILE.read_text(encoding="utf-8")
first_line = text.lstrip().splitlines()[0]
self.assertTrue(
first_line.startswith("# /expand"),
f"Command file must start with '# /expand', got: {first_line!r}",
)
def test_expand_covers_all_discovery_sources(self):
text = EXPAND_COMMAND_FILE.read_text(encoding="utf-8")
sources = [
"documents/cv/",
"documents/linkedin/",
"documents/diplomas/",
"documents/references/",
"GitHub Profile",
]
for src in sources:
self.assertIn(src, text, f"expand.md must include discovery source: {src}")
def test_expand_maps_github_projects_to_independent_projects_section(self):
text = EXPAND_COMMAND_FILE.read_text(encoding="utf-8")
self.assertIn("## Independent Projects", text)
self.assertIn("Independent Projects & Portfolio", text)
self.assertIn("GitHub — repo-name", text)
self.assertIn("Portfolio & projects grounded in code", text)
self.assertNotIn("documents/projects/", text)
def test_expand_enforces_additive_and_confirmation_principles(self):
text = EXPAND_COMMAND_FILE.read_text(encoding="utf-8")
self.assertIn("Additive only", text)
self.assertIn("User confirms before writing", text)
self.assertIn("`all`", text)
self.assertIn("`review`", text)
self.assertIn("`skip`", text)
if __name__ == "__main__":
unittest.main()