Skip to content

feat(projects): inherit the host's managed-projects registry (v0.4.0) - #25

Merged
mabry1985 merged 1 commit into
mainfrom
feat/adr0095-projects-projection
Jul 25, 2026
Merged

feat(projects): inherit the host's managed-projects registry (v0.4.0)#25
mabry1985 merged 1 commit into
mainfrom
feat/adr0095-projects-projection

Conversation

@mabry1985

Copy link
Copy Markdown
Member

protoAgent 0.115.0 added a top-level projects: registry (ADR 0095) — one place to declare a project, with consumers projecting from it instead of re-declaring it. This is the GitHub half.

What changes

A registered project's github field now feeds the repo picker and /issue:

# host config
projects:
  - name: protoAgent
    path: /Users/kj/dev/protoAgent
    github: protoLabsAI/protoAgent
  - name: notes
    path: /Users/kj/dev/notes
    github: protoLabsAI/notes-plugin

…and github.repos can stay empty. Declare a project once instead of also re-typing owner/name here.

Two deliberate properties

Explicit config wins. github.repos set ⇒ the registry is never consulted. Same non-regression property the core work has: configuring nothing new keeps today's behavior byte for byte.

The version floor stays 0.27.0. The projection is purely additive, and bumping to 0.115.0 would cut off older hosts that don't want it anyway. So the host read is lazy and broadly guarded — no host, a pre-0.115.0 host (no projects attribute), or config not yet loaded all yield [] rather than raising. Same posture as register()'s existing hasattr(registry, "live_config") fallback.

Design note

effective_default_repo stays a pure function — the registry arrives as its repos argument rather than being read inside it. That keeps /issue, the tools, and the picker agreeing on one answer, and meant zero churn in the existing tests. The host read lives in exactly one guarded place (projects.py), which api.py::_repos and register() both route through.

Tests

8 new host-free tests in tests/test_projects.py, covering all three degrade paths (no host / host without the registry / host whose config() raises), dedupe-and-order, explicit-wins, and the blank-only list — repos: ["", " "] is an empty list, not a configured one, so it falls through.

Gates: pytest -q 121 passed · ruff check clean.

Not yet verified against a live 0.115.0 instance — that's the next step before I'd call this done.

🤖 Generated with Claude Code

protoAgent 0.115.0 added a top-level `projects:` registry (ADR 0095) — one
place to declare a project, with consumers projecting from it instead of
re-declaring it. This is the GitHub half: a registered project's `github`
field now feeds the repo picker and /issue, so declaring a project once is
enough instead of also re-typing owner/name into `github.repos`.

Two properties, both deliberate:

Explicit config WINS. `github.repos` set => the registry is never consulted.
Same non-regression property the core work has — configuring nothing new
keeps today's behavior byte for byte.

The version floor stays 0.27.0. The projection is additive, and bumping to
0.115.0 would cut off older hosts that don't want it anyway. So the host
read is lazy and broadly guarded: no host (this suite), a pre-0.115.0 host
(no `projects` attribute), or config not yet loaded all yield [] rather than
raising. Same posture as register()'s existing hasattr(registry,
"live_config") fallback.

effective_default_repo stays PURE — the registry arrives as its `repos`
argument rather than being read inside it — so /issue, the tools and the
picker keep agreeing on one answer with no test churn.

8 host-free tests cover all three degrade paths plus dedupe/order,
explicit-wins, and the blank-only list (`repos: ["", " "]` is an empty list,
not a configured one).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mabry1985

Copy link
Copy Markdown
Member Author

Verified live against a real 0.115.0 host

Booted a fully isolated instance (own PROTOAGENT_BOX_ROOT, own instance id, free port — the live desktop fleet was never touched) with this branch symlinked in as the github plugin and a real registry:

projects:
  - {name: protoAgent,   path: /Users/kj/dev/protoAgent,    github: protoLabsAI/protoAgent,     default_branch: main}
  - {name: githubPlugin, path: /Users/kj/dev/github-plugin, github: protoLabsAI/github-plugin,  default_branch: master}
  - {name: notesOnly,    path: /Users/kj/dev/projectBoard-plugin, fs: false}   # no `github:` field

github:
  repos: []          # EMPTY — must inherit from the registry

GET /api/plugins/github/config:

{
  "repos": ["protoLabsAI/protoAgent", "protoLabsAI/github-plugin"],
  "default_repo": "protoLabsAI/protoAgent",
  "gh_available": true
}

Three things confirmed at once:

  • the picker populated from the registry with repos: [] configured;
  • notesOnly — registered but with no github: field — contributed nothing, so the projection filters rather than assuming every project is a GitHub repo;
  • default_repo fell through to the first registry entry, so /issue and the tools agree with the picker.

Plugin registration was clean: [github] registered 11 read tool(s) … + /issue command + board view.

Not observed live: nothing. This is the whole feature surface.

@mabry1985
mabry1985 merged commit 2c69022 into main Jul 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant