feat(projects): the registry is ADDED to an explicit repos list, never hidden by it (v0.5.0) - #26
Conversation
…r hidden by it (v0.5.0) v0.4.0 inherited the host's ADR 0095 projects: registry only when github.repos was EMPTY — an explicit list won outright. That turned "I typed a repos list once" into "the registry is dead for me forever": every project the agent onboarded afterwards (onboard_project registers into projects:, protoAgent #2925) stayed invisible to /issue and the board, silently, with no knob to opt back in (2026-08-20, protoEngineer: three self-onboarded repos never reached the picker). effective_repos = explicit entries (operator order, first — so default-repo resolution is unchanged) UNION registry repos, deduped. registry_repos also reads github: bindings on legacy filesystem.projects entries — a pre-registry instance, or one written by the pre-#2925 tool, carries them there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J4vmkfYfUE4LsK3rf4L7fk
There was a problem hiding this comment.
QA panel review — PASS
code-review-structural · head fa39d6903567 · formal
Overall risk is low: the PR deliberately flips projects.py::effective_repos from explicit-wins to a union (_dedupe([*explicit, *registry_repos()])), and the only confirmed issue is downstream docs, not runtime behavior. Fix first: rewrite the _repos docstring in api.py (now at lines ~83/84) to describe the union — explicit github.repos first, then the registry's repos, deduped — because its explicit-wins wording misdescribes the picker list at PR head. The panel did not disagree; verification confirmed the single minor finding, re-anchoring it from the stale line 80 to 83/84 and keeping the quote verbatim, with no refutations and nothing marked uncertain. Gaps: head-SHA and PR-resolver reads 404'd, so api.py was verified on the default branch (identical text since the diff doesn't touch it), and the actually-changed file projects.py itself drew no direct findings — only its consumer's stale docstring was flagged.
Findings
| Severity | Location | Finding | Verified | |
|---|---|---|---|---|
| 🟡 | minor | api.py:83 |
The consumer _repos docstring still documents the v0.4.0 explicit-wins contract ("explicit github.repos, else the registry"), contradicting the new union sem… |
confirmed |
findings JSON (machine-readable)
[
{
"file": "api.py",
"line": 83,
"severity": "minor",
"category": "conventions",
"claim": "The consumer `_repos` docstring still documents the v0.4.0 explicit-wins contract (\"explicit github.repos, else the registry\"), contradicting the new union semantics this PR ships, so the consumer's docs misdescribe the picker list it actually returns.",
"evidence": "def _repos(cfg: dict) -> list[str]:\n \"\"\"The picker list \u2014 explicit ``github.repos``, else the host's ADR 0095\n managed-projects registry (v0.115.0+; ``[]`` on older hosts).\"\"\"\n from .projects import effective_repos\n\n return effective_repos(cfg.get(\"repos\"))",
"verdict": "confirmed",
"note": "Quote found verbatim in api.py (re-anchored: `def _repos` at line 83, docstring 84-85; finding's line 80 is stale). PR diff changes effective_repos to `_dedupe([*explicit, *registry_repos()])` (union, explicit first) and does NOT touch api.py, so the consumer docstring's 'explicit repos, else the registry' explicit-wins wording misdescribes the returned picker list at PR head. Read caveat: head-SHA and PR-resolver reads 404'd; verified via default-branch read \u2014 identical text since api.py is untouched by the diff."
}
]1 finding(s) excluded from the verdict by in-diff confinement (file not among this PR's changed paths):
api.py(minor) — The consumer_reposdocstring still documents the v0.4.0 explicit-wins contract ("explicit github.repos, else the registry"), contradicting the new union sema
Why
v0.4.0 (#25) inherited the host's ADR 0095
projects:registry only whengithub.reposwas empty — an explicit list won outright. That turned "I typed a repos list once" into "the registry is dead for me forever": every project the agent onboarded afterwards (onboard_projectregisters intoprojects:as of protoAgent#2925) stayed invisible to/issueand the GitHub board, silently, with no knob to opt back in. Seen on protoEngineer today: an explicit 5-repo list, and three self-onboarded repos (qaEngineer, mythxengine, promptlab-plugin) with correctgithub:bindings that never reached the picker.What
effective_repos= explicit entries (operator order, first — soeffective_default_reporesolution is byte-identical for everything the list names) ∪ registry repos, deduped.registry_reposalso readsgithub:bindings on legacyfilesystem.projectsentries — a pre-registry instance, or one written by the pre-#2925 onboard tool, carries them there. Registry entries lead.Still non-regressing for: an empty list (same as before), an explicit list on a host with no registry (same as before), and every entry an explicit list names (same entries, same order). The only observable change: registry repos now appear after an explicit list instead of being dropped.
Companion: protoAgent#2925 (onboard_project writes the registry).
Gate:
ruff check . && ruff format --check . && pytest -q→ 122 passed.🤖 Generated with Claude Code
https://claude.ai/code/session_01J4vmkfYfUE4LsK3rf4L7fk