Skip to content

chore: sync upstream → protoAgent v0.20.0#64

Merged
mabry1985 merged 6 commits into
mainfrom
chore/sync-upstream-20260607
Jun 7, 2026
Merged

chore: sync upstream → protoAgent v0.20.0#64
mabry1985 merged 6 commits into
mainfrom
chore/sync-upstream-20260607

Conversation

@mabry1985
Copy link
Copy Markdown
Contributor

Upstream sync (merge commit). 5 new commits, zero conflicts (base anchored at v0.19.0).

What comes in

Install plugins from a git URL (ADR 0027) — python -m server plugin install <url> (+ list/uninstall/sync/install-deps) + a console Plugins panel. Safety: install ≠ enable ≠ trust, pinned plugins.lock, declare-only deps, optional source allowlist, audit. Full-bundle repos (tools+subagents+skills+workflows+views auto-discovered).

pytest -q → green. Merge as a MERGE COMMIT (--merge).

🤖 Generated with Claude Code

mabry1985 and others added 6 commits June 6, 2026 16:39
…7, PR1) (#623)

Author a plugin in its own GitHub repo, install it by URL — the deferred Slice 5
of the extensibility arc, done with a real safety model (vs ComfyUI's clone=RCE).

- graph/plugins/installer.py: clone (--depth1, no submodules) at a ref → resolve
  commit SHA → validate manifest → move into the live plugins dir (already on
  loader._plugin_roots) → record in a committed plugins.lock. install/uninstall/
  list/sync. Refuses to shadow a built-in, rejects a manifest-less repo, strips
  .git, optional plugins.sources.allow allowlist. Lock path env-overridable.
- graph/plugins/cli.py + server `plugin` subcommand: `python -m server plugin
  install <url> [--ref] [--force] | list | uninstall <id> | sync`. Dispatched
  before the server argparse; fetches code and exits.
- manifest: requires_pip / repository / homepage / min_protoagent_version.
- .gitignore: config/plugins/ (installed code, reproducible via lock+sync);
  plugins.lock stays committed.

Safety (ADR 0027): install ≠ enable ≠ trust. Install only puts code on disk +
reads the manifest as data — never imports the plugin, never pip-installs deps
(requires_pip declared, installed explicitly). Enabling (plugins.enabled →
register()) is the trust decision; untrusted code → MCP.

Tests: 9 installer cases (fetch+lock+no-enable, tag pin, force, builtin-shadow
guard, no-manifest reject, bad-scheme, uninstall, sync-reclone, allowlist).
Full suite 1136 passed; ruff clean; CLI live-smoked install→list→uninstall.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…624)

Install plugins from a git URL in the console (Settings → Integrations), for
non-CLI users. Mirrors the delegates panel.

- operator_api/plugin_routes.py: GET /api/plugins/installed (lock entries enriched
  with manifest + declared capabilities + enabled state), POST /api/plugins/install
  ({url, ref?, force?} → summary + restart_required), DELETE /api/plugins/{id}.
  Wired into the server route registration.
- apps/web PluginsSection: install form (URL + optional ref) + installed list with
  a review surface (version, source, SHA, views, deps-to-install, env, secrets,
  capabilities), enabled badge + the "add to plugins.enabled + restart" hint, and
  uninstall. Rendered under Integrations (now always shown — Plugins is core).
  api/types/queries + CSS.

install ≠ enable holds in the UI: installing fetches code (no run); enabling is the
config+restart step, surfaced as a hint. Untrusted → MCP (linked).

Tests: e2e plugin-install.spec (install → row shows NOT enabled + enable hint →
uninstall; form gating). 11 console specs green; web build green; ruff clean.
Live wire-smoke: POST install → GET installed (present, enabled=false, views) →
DELETE, against a real server with an isolated lock/plugins dir.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The safety rails for git-URL installs.

- install-deps: `python -m server plugin install-deps <id>` pip-installs a plugin's
  declared requires_pip — the explicit, separate code-exec step that `install`
  deliberately skips. When an enabled plugin's deps are missing, the loader now
  emits a clear diagnostic ("declared deps not installed (…) — run: … install-deps
  <id>") instead of a raw ModuleNotFoundError.
- audit: install / uninstall / install-deps are recorded to the audit log
  (session_id=plugins, tool=plugin.*) with url/sha/deps.
- allowlist: `plugins.sources.allow` (host/org globs, e.g. github.com/org/*) is a
  new config field, enforced on both console (route reads cfg) and CLI installs
  (reads the live config). Empty = any URL (gated). Off-allowlist → refused.

Tests: install-deps (noop/missing/runs-pip-with-deps via a mocked subprocess),
configured_allowlist config read. 32 installer/plugin cases; full suite 1140;
ruff clean. CLI-smoked: allowlist block/allow + install-deps.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…+ docs (ADR 0027, PR4) (#626)

A plugin repo now contributes the WHOLE extension set, not just tools — so
installing a git repo pulls in everything it ships.

- register() already covers tools / subagents / routes / MCP / views. PR4 adds
  auto-discovery of conventional DATA subdirs in each enabled plugin (no
  boilerplate): skills/ (SKILL.md) → skills index, workflows/ (*.yaml) →
  WorkflowRegistry. Plus registry.register_workflow_dir() for non-standard paths.
- loader collects workflow_dirs (registry + conventional) and the conventional
  skills/ dir; PluginLoadResult.workflow_dirs; STATE.plugin_workflow_dirs;
  _build_workflow_registry appends plugin workflow dirs (before the writable dir,
  so user-saved recipes still win a name clash).
- docs/guides/plugin-registry.md: install (CLI + console) + publish the full
  bundle (repo layout + register() + skills/workflows/views + requires_pip) +
  the safety model (install≠enable, lock/pin, allowlist, untrusted→MCP). Sidebar +
  ADR 0027 updated.

Tests: plugin workflow + skill auto-discovery, register_workflow_dir. 34
installer/plugin cases; full suite 1142; ruff clean. Live-smoked end-to-end:
installed a repo shipping a tool + workflows/recipe.yaml + skills/ → enabled →
tool loaded AND `plugin-recipe` appears in /api/workflows.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@protoquinn
Copy link
Copy Markdown

protoquinn Bot commented Jun 7, 2026

👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow.

Copy link
Copy Markdown

@protoquinn protoquinn Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA Audit — PR #64 | chore: sync upstream → protoAgent v0.20.0

VERDICT: WARN (preliminary — CI not yet terminal)


CI Status

  • Python tests: queued
  • Web E2E smoke: queued
  • Lint (ruff): queued
  • Verify workspace config: queued
  • A2A live smoke: queued

Diff Review
Large upstream sync (1625-line diff, 5 commits, zero conflicts). Brings ADR 0027 — install plugins from a git URL with install ≠ enable ≠ trust, pinned SHA lock, allowlist, audit logging, install-deps step, and a console Plugins panel. Full-bundle repos (skills + workflows auto-discovered). Merge commit strategy as specified.

Visible diff (first 200 lines) shows: .gitignore plugin dir exclusions, CHANGELOG.md for v0.20.0, e2e mock server plugin routes, new plugin-install.spec.ts (install → uninstall round-trip), plugin panel CSS, and api.ts type additions. Clean scope.

Observations

  • Gap: Full diff is 1625 lines — backend plugin-install implementation (git clone, allowlist enforcement, pip install-deps, manifest parsing) is in the truncated portion. Cannot fully assess security correctness of the git-fetch + pip-invoke path without the full diff.
  • Gap: Clawpatch unavailable for protoLabsAI/roxy (not in project registry). Structural review deferred.
  • CI not yet terminal — this is a pre-merge COMMENT; will re-verify and upgrade to APPROVE once all checks are green and no blocking findings surface from the full diff.

— Quinn, QA Engineer

@protoquinn
Copy link
Copy Markdown

protoquinn Bot commented Jun 7, 2026

Submitted COMMENT review on protoLabsAI/roxy#64. CI is still queued — this is a pre-merge non-blocking note. I'll re-verify once all checks are terminal and upgrade to APPROVE if nothing blocking surfaces from the full diff.

Copy link
Copy Markdown

@protoquinn protoquinn Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI terminal-green, no blockers on prior review — auto-approving on green (#748).

@mabry1985 mabry1985 merged commit 9f50df8 into main Jun 7, 2026
5 checks passed
@mabry1985 mabry1985 deleted the chore/sync-upstream-20260607 branch June 7, 2026 00:30
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