diff --git a/.claude/commands/expand.md b/.claude/commands/expand.md index aac4261..4643560 100644 --- a/.claude/commands/expand.md +++ b/.claude/commands/expand.md @@ -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: - Fetch the repository 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) 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.) **Methods and Practices** (agile, version control, reproducibility, testing, etc.) **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: - The competency name - 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 +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`. --- ## 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 @@ -131,6 +138,11 @@ Source: [Course/cert name — Provider] + [Competency 2] ... +**PROJECTS & PORTFOLIO** +Source: [GitHub — repo-name] + + [Project Name]: [Problem, stack, and outcome] + ... + **GITHUB — [repo-name]** Source: README + inferred from tech stack + [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. ### 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 - Domain knowledge → append to the Domain Knowledge or Technical Skills section (match the existing structure) - Methods and practices → append appropriately @@ -189,7 +202,7 @@ After writing, present: ## /expand Complete ### 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 [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. - **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. +- **Portfolio & projects grounded in code.** Independent projects added to the profile must reflect real projects found in public GitHub repositories — never fabricated project claims. diff --git a/CHANGELOG.md b/CHANGELOG.md index 8887848..2c55f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,12 @@ per-file diff commands. ### 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`, `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 diff --git a/tests/test_expand_command.py b/tests/test_expand_command.py new file mode 100644 index 0000000..2413fdd --- /dev/null +++ b/tests/test_expand_command.py @@ -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() +