## Code Review: `--github-repo` cross-platform PR lookups

### ftl_project_expert/cli.py:init
VERDICT: CONCERN
CORRECTNESS: QUESTIONABLE
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: N/A
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: The `--github-repo` option is accepted and saved for any platform, but there's no validation that the value is in `owner/repo` format. A typo like `--github-repo myrepo` (missing owner) would silently save and only fail later at `gh` call time during `research`. The `gh` CLI existence check at init time is good but insufficient — `gh auth status` would catch the more common failure of an unauthenticated install. Minor: passing `--github-repo` with `--platform github` is redundant but harmless since `research` guards with `config["platform"] != "github"`.

---

### ftl_project_expert/cli.py:_fetch_artifacts
VERDICT: PASS
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: N/A
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: The routing logic is sound. PRs fall back to `github_source` when the primary source lacks `get_pr` (e.g., Jira). Numeric issue refs on Jira are correctly routed to GitHub since Jira uses string keys like `PROJ-123`, not `#123` — the old code would have passed an integer to `JiraSource.get_issue()` which expects a key string, likely crashing. Both `github_source.get_pr()` and `github_source.get_issue()` can raise `RuntimeError` per the observation, but the existing `except Exception` block handles those gracefully. The optional `github_source=None` default preserves backward compatibility for all existing callers. The informational fallback messages (`"no GitHub repo configured"`) are helpful.

---

### ftl_project_expert/cli.py:research
VERDICT: PASS
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: N/A
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: The `GitHubSource` instantiation is correctly guarded by both `gh_repo` being set and `platform != "github"` (avoiding a redundant second GitHub source). The `github_source` is created once and shared across all `_research_one` calls via closure, which is efficient. The diagnostic message to stderr is appropriate. The `github_source` is properly threaded through to `_fetch_artifacts`.

---

### ftl_project_expert/cli.py:status
VERDICT: PASS
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: N/A
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: Straightforward conditional display of the `github_repo` config value. Consistent with the existing status output pattern.

---

## Summary

The feature is well-integrated end-to-end: `init` saves config, `research` reads it and creates the cross-platform source, `_fetch_artifacts` uses it with sensible fallback logic, and `status` displays it. The main improvement to the old code is fixing the silent mishandling of numeric issue refs on Jira and PRs on platforms without `get_pr`.

**Two items worth addressing:**

1. **No format validation on `--github-repo`** — A simple regex check for `\w+/\w+` in `init` would catch obvious typos before they're persisted.
2. **Zero test coverage** — The entire `cli.py` has no tests per the observation. The new cross-platform routing logic in `_fetch_artifacts` has several branches (Jira+numeric+github_source, Jira+numeric+no_github_source, pr+has_get_pr, pr+github_source, pr+neither) that would benefit from unit tests, especially since they fix a prior bug with numeric refs on Jira.

---

### SELF_REVIEW
LIMITATIONS: Could not see the full `init` function body to verify how the `github_repo` block interacts with all platform-specific config builders (only saw the diff hunks and surrounding context). Could not verify whether other commands besides `research` call `_fetch_artifacts` indirectly — the observation only shows direct callers, not transitive ones. No test files exist to check for breakage.

---

### FEATURE_REQUESTS
- Include the full function body for the `init` command (it was truncated in observations) to verify interaction with all platform config builders
- When test coverage is zero, flag it more prominently in the observation output so the reviewer can weigh whether to BLOCK vs CONCERN

---
