Skip to content

feat: add poly update command and startup version check - #303

Merged
Ruari-Phipps merged 14 commits into
mainfrom
ruari/feat/poly_update
Sep 10, 2026
Merged

feat: add poly update command and startup version check#303
Ruari-Phipps merged 14 commits into
mainfrom
ruari/feat/poly_update

Conversation

@Ruari-Phipps

@Ruari-Phipps Ruari-Phipps commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a poly update command that detects how the CLI was installed, runs the matching upgrade command, and refreshes the installed AI agent skills, supporting --check, --to VERSION, --cli-only, and --skills-only. Also adds a passive startup notice that tells users when a newer release exists, limited to standalone tool installs.

Final PR of the stack: stacked on #305 (poly setup), whose skills wrapper it reuses.

Motivation

There is no built-in way to update the CLI. Users have no way of learning that a new version exists, and upgrading means knowing which of several install methods they used and running the right command by hand.

Changes

  • Add poly update, which upgrades the CLI to the latest release on PyPI.

  • Add poly update --check to report whether an update is available without installing it.

  • Add poly update --to VERSION to install a specific release, including downgrades and reinstalls. Named --to rather than --version because the root parser already uses that to print the installed version. The requested version is validated against PyPI first, so a typo fails immediately with a list of recent releases rather than a resolver error.

  • Detect the install method from sys.prefix and package metadata, and pick the matching command for uv tool, pipx, uv pip and pip. Pinned installs use install --force rather than upgrade, since the upgrade subcommands will not move backwards and would silently no-op a downgrade.

  • Refuse to upgrade an editable/dev install, which would otherwise replace a working checkout with a released package and leave local edits mysteriously inert.

  • Refuse to upgrade an ephemeral uvx / uv run environment, where the install is discarded when the command exits.

  • Add a passive update notice on CLI startup, rate limited to once every 12 hours via a stamp file in ~/.poly. It is restricted to standalone uv tool / pipx installs: a project install's version is pinned by that project's manifest, so prompting the user to upgrade it would be advice the next dependency sync silently undoes.

  • Suppress the startup notice for --json and non-TTY output so machine-readable output cannot be corrupted, via POLY_NO_UPDATE_CHECK, and in CI. Non-TTY already covered most CI runners, but only incidentally, and that stops holding for any runner that allocates a terminal, so the usual markers are checked explicitly. Jenkins, Azure Pipelines and TeamCity are named individually because they do not set CI. Errors are swallowed and logged at debug level so a version check can never break the command the user actually ran.

  • Mention POLY_NO_UPDATE_CHECK in poly update --help, so someone who sees the notice can find out how to silence it. No --no-update-check flag: the env var already works inline (POLY_NO_UPDATE_CHECK=1 poly status), so a flag would only duplicate it across every subcommand's help output.

  • Gate the startup check cheapest-first — string comparison, then a small file read, then a 2 second network call — so the common case adds no measurable startup cost. Skip recording the stamp when PyPI does not answer, so a transient failure retries on the next run instead of causing 12 hours of silence.

  • Add PyPI helpers to cli_commands/shared.py: get_latest_version, get_available_versions and is_newer_version. Version comparison uses packaging rather than string inequality, which previously reported an update available on every run for any build not exactly matching PyPI.

  • Add a shared POLY_HOME_DIR constant and use it for both the credentials file and the update stamp, replacing an inlined ~/.poly path.

  • Declare packaging>=24.0, which was previously only available transitively.

  • Update the installed AI agent skills as part of poly update — also when the CLI is already current — via the pinned npx skills wrapper this PR inherits from feat: add poly setup command and remove poly start #305.

  • Add --cli-only and --skills-only (mutually exclusive) to narrow the update to one half. --skills-only deliberately skips the not-upgradable guard, so editable/dev installs can still update their skills.

  • Treat skill failures in a combined update as best-effort: warn without failing the command. With --skills-only they are the whole command failing (exit 1).

  • Capture npx output in --json mode so stdout stays a single object, and report the outcome under a skills_updated key.

Test strategy

  • Added/updated unit tests
  • Manual CLI testing (poly <command>)
  • Tested against a live Agent Studio project
  • N/A (docs, config, or trivial change)

101 unit tests covering the skills half of the update (scope flags, best-effort vs required failure handling, quiet npx in --json mode), install-method detection, version comparison and ordering, command construction for each install method, target-version validation, the update control flow, and every startup-check and suppression gate. Tests make no network calls and never touch the real ~/.poly.

Manual testing covered --check, --to with valid, invalid and older versions, and the editable-install guard.

Checklist

  • ruff check . and ruff format --check . pass
  • pytest passes
  • No breaking changes to the poly CLI interface (or migration path documented)
  • Commit messages follow conventional commits

Screenshots / Logs

Startup notice gates, verified across every path:

scenario network call stamp written result
uv tool install, update available yes yes notice shown
pipx install, update available yes yes notice shown
project venv no no silent
ephemeral uvx no no silent
--json output no no silent
piped, not a TTY no no silent
POLY_NO_UPDATE_CHECK=1 no no silent
CI (CI, JENKINS_URL, TF_BUILD, TEAMCITY_VERSION) no no silent
checked within last 12 hours no no silent
PyPI unreachable yes no silent
already up to date yes yes silent

Invalid target version:

$ poly update --to 99.99.99
Error: Version '99.99.99' not found on PyPI. Recent versions: 0.53.1, 0.53.0, 0.52.0, 0.51.0, 0.50.0
$ echo $?
1

@Ruari-Phipps
Ruari-Phipps requested a review from a team September 2, 2026 11:31
@github-actions

This comment has been minimized.

@linear-code

linear-code Bot commented Sep 2, 2026

Copy link
Copy Markdown

DEVP-454

@github-actions

This comment has been minimized.

Ruari-Phipps and others added 2 commits September 2, 2026 15:15
Five skills teaching AI coding agents (Claude Code, Cursor, Codex) the
poly CLI workflow, structured against google/agents-cli conventions:

- poly-adk-workflow: entrypoint - setup, core loop, invariants, routing
- poly-adk-testing: validate, scripted chat, test_suite, functions execute
- poly-adk-branching: merge model, conflict resolution, review gists
- poly-adk-conversations: real-call inspection, logging/metrics
- poly-adk-rtc: RTC cycle, drift protection, live-push safety

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
poly setup is the single onboarding entry point: auth (browser sign-in),
shell completion, AI agent skills via npx, and project setup — each step
skipped automatically when already done.

- new cli_commands/skills.py: pinned npx skills wrapper, Node 18+ gate,
  non-fatal install/update helpers
- poly login/setup now wait for a new API key to become active
- region selection extracted and threaded everywhere (no hardcoded studio)
- poly start removed: superseded by poly setup, not referenced in
  published material
- docs: new setup reference page, getting-started restructured around
  poly setup, start page removed, tooling page leads with skills install

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Ruari-Phipps
Ruari-Phipps force-pushed the ruari/feat/poly_update branch from eaf8ce3 to 77b7d02 Compare September 2, 2026 15:39
@Ruari-Phipps
Ruari-Phipps requested a review from a team as a code owner September 2, 2026 15:39
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Ruari-Phipps
Ruari-Phipps force-pushed the ruari/feat/poly_update branch from 77b7d02 to 7c6b03d Compare September 2, 2026 15:40
@Ruari-Phipps
Ruari-Phipps changed the base branch from main to feat/poly-setup September 2, 2026 15:40
@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

Ruari-Phipps and others added 9 commits September 2, 2026 16:49
Path.expanduser resolves ~ from USERPROFILE on Windows, not HOME, so the
throwaway home directory must be set via both variables.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
polyai-adk now imports packaging directly for PyPI version comparison, so
declare it rather than relying on it being present transitively.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An editable or ephemeral install was only rejected inside perform_update,
after the target version had been validated against PyPI and after
"Updating Poly CLI to version X..." had already been printed. The command
announced an update it then refused to perform, and spent a network round
trip to do it.

Hoist the guard to the top of update() so a refused install produces the
warning and nothing else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI runners have nobody watching for an upgrade prompt. Non-TTY output
already covered most of them, but that is incidental rather than
deliberate and stops holding for any runner that allocates a terminal, so
check the usual markers explicitly. Jenkins, Azure Pipelines and TeamCity
are named individually because they do not set CI.

Suppression reasons move into one helper so they are read together, and
'poly update --help' now mentions POLY_NO_UPDATE_CHECK. That closes the
discoverability gap that made a --no-update-check flag look necessary:
the env var already works inline, so a flag would only duplicate it
across every subcommand's help output.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
poly update now refreshes the installed skills after the CLI (also when
the CLI is already current). --cli-only and --skills-only narrow it to
one half; --skills-only works on editable installs, where the CLI half
is refused. Skill failures in a combined update warn without failing
the command; in --json mode npx output is captured so stdout stays a
single object.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

@jamesosullivan-polyai jamesosullivan-polyai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved — solid implementation with strong test coverage (101 tests), scope is clear (updates the CLI tool + bundled skills, not project resources), and correctly wired into cli.py.

Note: this PR isn't mergeable standalone as-is — it imports node_gate_reason/update_skills from skills.py and GETTING_STARTED_GROUP from base.py, which only land in #305. Merge #305 first; expect a straightforward conflict in cli.py's COMMANDS list when landing sequentially. Also worth a quick pass on the stray copy-pasted docstring in update.py:230 ("Auth command family: start and login.").

Ruari-Phipps added a commit that referenced this pull request Sep 10, 2026
## Summary

Adds a `skills/` directory with five agent skills that teach AI coding
agents (Claude Code, Cursor, Codex, etc.) the `poly` CLI workflow, plus
a README describing the suite. Installable via `npx skills add`.

First PR of a three-part stack: #305 adds `poly setup`, which installs
these skills, and #303 makes `poly update` keep them current.

## Motivation

AI coding agents working on ADK projects currently have no contextual
knowledge of the `poly` workflow — resource schemas, the no-`main` rule,
pushed-state testing semantics, or conflict resolution. These skills
provide that context on demand, structured after Google's `agents-cli`
skills suite: a workflow entrypoint plus task-specific skills that load
only when relevant.

## Changes

- `skills/poly-adk-workflow/SKILL.md` — entrypoint: install/update,
auth, `poly docs` habit, resource-choice guidance, project structure,
the core edit → validate → push → test → merge loop, and a routing table
to the task skills
- `skills/poly-adk-testing/SKILL.md` — `poly validate`, scripted `poly
chat`, `test_suite/` authoring with `api_mocks`, `poly functions
execute/validate`
- `skills/poly-adk-branching/SKILL.md` — branch semantics, three-way
merge model, conflict markers, non-interactive `merge --resolutions`,
review gists
- `skills/poly-adk-conversations/SKILL.md` — `poly conversations`,
instrumenting with `conv.log` and metrics, real-call → test-case loop
- `skills/poly-adk-rtc/SKILL.md` — RTC pull/push cycle, drift
protection, live-environment safety
- `skills/README.md` — suite overview and install instructions

Resource schemas are deliberately not duplicated — skills instruct
agents to run `poly docs`, which ships schemas with the installed CLI.
Skill `metadata.version` is pinned to the current release (0.53.1).

## Test strategy

- [ ] Added/updated unit tests
- [x] Manual CLI testing (`poly <command>`)
- [x] Tested against a live Agent Studio project
- [x] N/A (docs, config, or trivial change)

Markdown-only change. Skills were installed locally via `npx skills add`
(frontmatter validated by the tool) and exercised in Claude Code
sessions against a real project. All CLI commands and flags referenced
were cross-checked against `docs/` and, where relevant, the source.

## Checklist

- [x] `ruff check .` and `ruff format --check .` pass
- [x] `pytest` passes
- [x] No breaking changes to the `poly` CLI interface (or migration path
documented)
- [x] Commit messages follow [conventional
commits](https://www.conventionalcommits.org/)

## Screenshots / Logs

N/A

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Ruari-Phipps added a commit that referenced this pull request Sep 10, 2026
## Summary

Adds `poly setup` — a single onboarding command covering authentication,
shell completion, AI agent skill installation, and project setup — and
removes `poly start`, which it supersedes. Second PR of the stack:
stacked on #304 (the skills it installs), and the base for #303, which
makes `poly update` keep them current.

## Motivation

Onboarding currently spans several commands users must discover one by
one (`poly login`, `poly completion`, `poly project create`), and the
new agent skills had no installation path. `poly setup` runs all of it
in one command, skipping any step that is already done, so it doubles as
a repair command. `poly start` covered a subset of this (auth + project,
hardcoded to the `studio` region) and is not referenced in published
material, so it is removed rather than left as a second entry point.

## Changes

- New `poly setup` command with `--region`, `--base-path`,
`--skip-auth`, `--skip-skills`, `--agent` (repeatable), `--dev`, and
`--global/-g` flags
- New `cli_commands/skills.py`: wrapper around the pinned `npx skills`
package with a Node.js 18+ gate; skill installation is non-fatal — a
missing Node warns and setup continues
- `poly login` (and setup) now wait up to 20s for a newly created API
key to become active before returning
- Region selection extracted to a shared picker; `poly start`'s four
hardcoded `studio` call sites removed along the way
- `poly start` removed from the CLI, docs, and nav
- Docs: new `setup` reference page; getting-started restructured to
"install, then `poly setup`"; tooling page now leads with skill
installation via setup
- `poly-adk-workflow` skill updated to mention `poly setup` for fresh
machines
- Root README quickstart updated from `poly start` to `poly setup`

## Test strategy

- [x] Added/updated unit tests
- [x] Manual CLI testing (`poly <command>`)
- [ ] Tested against a live Agent Studio project
- [ ] N/A (docs, config, or trivial change)

60 new tests (node gate, npx argument construction and non-raising
failures, per-step skip logic, real rc-file completion installs in
throwaway home directories — set via both HOME and USERPROFILE so they
are hermetic on Windows — region threading, and activation-poll
behavior). Manually verified end-to-end with an isolated `$HOME`:
completion install + idempotent re-run, `--dev -g --agent claude-code`
installing all five skills via npx, graceful skip without a TTY, and
`poly start` now reporting an invalid choice.

## Checklist

- [x] `ruff check .` and `ruff format --check .` pass
- [x] `pytest` passes
- [x] No breaking changes to the `poly` CLI interface (or migration path
documented) — `poly start` is intentionally removed; `poly setup` /
`poly login` are the migration path
- [x] Commit messages follow [conventional
commits](https://www.conventionalcommits.org/)

## Screenshots / Logs

N/A
Base automatically changed from feat/poly-setup to main September 10, 2026 10:10
@Ruari-Phipps
Ruari-Phipps enabled auto-merge (squash) September 10, 2026 10:17
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Base (main) PR Change
79.3% 79.3% +0.0% ✅

Changed file coverage

File Coverage Change
poly/utils/credentials.py 22.0% +1.3% ✅
poly/cli_commands/shared.py 65.7% +2.9% ✅
poly/cli.py 81.2% +0.6% ✅

@Ruari-Phipps
Ruari-Phipps merged commit 4b6d5c9 into main Sep 10, 2026
6 checks passed
@Ruari-Phipps
Ruari-Phipps deleted the ruari/feat/poly_update branch September 10, 2026 10:18
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.

2 participants