Skip to content

feat(view): route 'view versions' to the registry when a default is configured#1938

Merged
danielmeppiel merged 5 commits into
microsoft:mainfrom
nadav-y:feat/view-versions-registry-routing
Jun 28, 2026
Merged

feat(view): route 'view versions' to the registry when a default is configured#1938
danielmeppiel merged 5 commits into
microsoft:mainfrom
nadav-y:feat/view-versions-registry-routing

Conversation

@nadav-y

@nadav-y nadav-y commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

apm view <pkg> versions decided registry-vs-git only from the lockfile, so an unlocked shorthand fell through to git ls-remote even when a default registry was configured. That contradicts apm install, which already routes unscoped shorthands to the default registry:

# default registry configured; package not yet installed
$ apm view jfrog/packages-skills versions
[x] Failed to list versions ... Authentication failed for list refs on github.com.   # before

It now consults the default registry for unlocked shorthands, and adds an explicit --registry [NAME] override.

Routing precedence (display_versions)

  1. --registry [NAME] -- force the registry path. Bare uses the lockfile/default; a value names a specific registry (clear error if unknown).
  2. Lockfile records the package as source: registry (existing behavior).
  3. Default registry configured + plain shorthand -- consult the registry, mirroring apm install. An explicit git URL (https://github.com/...) stays on the git path.
  4. Otherwise -- git.

A full git URL is the escape hatch to force git when a default registry is set (the view analog of the - git: manifest form).

Why this is low-risk

All paths here are read-only -- no install, no resolution, no lockfile mutation. This is the read-only sibling of the deferred default-registry-vs-git-transitives discussion, without any of that risk. _display_registry_versions already resolved the default registry for unlocked packages (it just wasn't reached); this wires the routing and adds explicit name support.

Behavior

Invocation (default registry configured) Before After
view org/repo versions (unlocked shorthand) git ls-remote (404/auth fail) default registry
view org/repo versions (locked as registry) registry registry (unchanged)
view org/repo versions --registry n/a (flag new) default registry
view org/repo versions --registry NAME n/a named registry (error if unknown)
view https://github.com/org/repo versions git git (escape hatch)
no default registry configured git git (unchanged)

Tests

4 new cases in tests/unit/test_view_command.py: default-registry routing for unlocked shorthand, no-default-still-git, --registry NAME forces + threads the name, and git-URL-forces-git. 331 view/registry tests pass; ruff clean. Verified live against a JFrog registry (unlocked listing, named registry, unknown-name error, git escape).

apm-spec-waiver: read-only display routing -- makes view versions consult the configured default registry consistently with install; no install, resolution, or lockfile behavior changes

Copilot AI review requested due to automatic review settings June 28, 2026 07:47

Copilot AI 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.

Pull request overview

This PR updates apm view <pkg> versions so that an unlocked shorthand (org/repo) routes to the configured default registry (mirroring apm install), and adds an explicit --registry [NAME] override to force the registry path.

Changes:

  • Add registry-routing precedence to display_versions, including default-registry routing for unlocked shorthands and a new --registry [NAME] flag.
  • Extend _display_registry_versions to accept an optional registry_name override and surface a clear error for unknown names.
  • Add unit tests covering default-registry routing, no-default fallback to git, explicit named-registry forcing, and git-URL escape hatch.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/apm_cli/commands/view.py Adds --registry [NAME], default-registry routing for unlocked shorthands, and registry-name threading into the registry version listing path.
tests/unit/test_view_command.py Adds unit tests validating the new routing behavior and --registry NAME forcing behavior.

Comment thread src/apm_cli/commands/view.py Outdated
Comment thread src/apm_cli/commands/view.py
Comment thread tests/unit/test_view_command.py
@nadav-y nadav-y added the panel-review Trigger the apm-review-panel gh-aw workflow label Jun 28, 2026
@github-actions

Copy link
Copy Markdown

APM Review Panel: ship_with_followups

Routing fix is sound and read-only; CHANGELOG + view.md, a local-path auth guard, and a source-disclosure annotation are the three in-PR additions needed before merge.

cc @nadav-y @danielmeppiel @sergio-sisternes-epam -- a fresh advisory pass is ready for your review.

The routing fix is architecturally sound and appropriately scoped: read-only, feature-gated, registry URL is config-derived with no SSRF vector, and the feature gate fails closed. Supply-chain-security found no blocking issues. Three areas need attention before merge.

The documentation debt is the sharpest mandatory gap. APM's operating principle requires a CHANGELOG entry for every user-facing behavior change, and this PR changes a longstanding behavior (plain shorthand falling through to git when a default registry is configured) while adding a new CLI flag. Both must appear in CHANGELOG.md [Unreleased] and docs/reference/cli/view.md (Options table, routing description, and an Examples entry) before merge. Doc-writer and oss-growth-hacker converge here; this is two file edits. The auth-expert's local-path finding is a real functional gap: apm view ./local-pkg versions with a default registry configured causes _is_explicit_git_form('./local-pkg') to return False, step 3 fires, and registry credentials are dispatched for a nonsensical query. dep_ref.is_local is available as a clean guard and is a one-line fix. Source disclosure is convergent across cli-logging-expert, devx-ux-expert, and oss-growth-hacker: the routing announcement is entirely absent. The same command produces a Version/Published table on a machine with a default registry and git refs on clean CI with no indication why. The performance-expert independently identified that the _effective_default_registry result is discarded and _display_registry_versions re-reads the lockfile; capturing and threading that result simultaneously provides the string for a logger.info announcement and eliminates the redundant I/O -- one structural change delivers both fixes.

The _effective_default_registry duplication (python-architect) is the most architecturally substantive finding but does not need to block this PR. The two functions diverge on user-fallback behavior, creating drift risk if registry_wiring's feature gate changes. A clean delegation is the right long-term fix and can be a scoped follow-up issue. The test-coverage-expert's integration-tier gap is similarly acceptable as a follow-up; the two missing-evidence unit findings (unknown-registry error path, .git-suffix branch) should be addressed in the next PR touching this path.

Dissent. The devx-ux-expert challenges the bare --registry form as redundant vs. auto-routing and a deviation from npm/pip/cargo idioms that require a value. The PR author explicitly designed it as a scriptable 'use lockfile/default' override. I side with the PR author: the bare form gives an explicit, scriptable signal that survives in shell history and Makefile targets, and APM's --registry [NAME] optional-value pattern is already established for apm install. Cli-logging-expert and devx-ux-expert independently identified the missing source-disclosure line; these converge on the same user-facing requirement and the exact insertion point is an implementation detail for the author.

Aligned with: Pragmatic as NPM, Secure by Default, OSS Community Driven

Growth signal. This is the second of three registry-parity beats (install had it since #1816). The JFrog/Artifactory evaluator cohort gets a concrete 'it just works' moment: apm view now follows your registry config, just like apm install. The CHANGELOG entry is the primary conversion surface -- the '[Fixed] apm view org/repo versions now routes to the configured registry for unlocked shorthands' line is the sentence that turns an evaluator's Slack message into real adoption.

Panel summary

Persona B R N Takeaway
Python Architect 0 2 2 _effective_default_registry duplicates feature-gate logic from registry_wiring with subtly different user-fallback behavior; _pr alias and double-normalization are minor friction.
CLI Logging Expert 0 1 3 Silent auto-registry routing emits no [i] message; users cannot tell why they got registry results instead of git refs.
DevX UX Expert 0 5 1 --registry silently dropped without versions field, view.md stale, no source disclosure on auto-route.
Supply Chain Security 0 0 3 No blocking security findings; routing is read-only, registry URL is config-derived (no SSRF), feature gate fails closed.
OSS Growth Hacker 0 2 2 Strong 'it just works' fix for registry users -- CHANGELOG entry missing and view.md stale; add both to capture the conversion signal.
Auth Expert 0 1 1 No credential leakage or auth bypass found; one local-path routing gap fires registry auth when no auth should be needed.
Doc Writer 0 4 1 reference/cli/view.md needs --registry in Options and updated routing description; CHANGELOG.md missing feat+fix entries.
Test Coverage Expert 0 2 1 2 recommended gaps: --registry UNKNOWN error path untested; no integration-tier test for default-registry routing.
Performance Expert 0 1 2 I/O overhead is noise vs the registry network call; recommended: thread _effective_default_registry result to avoid a second LockFile.read.

B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.

Top 5 follow-ups

  1. [doc-writer + oss-growth-hacker] Add CHANGELOG.md [Unreleased] entry for routing fix and --registry flag; update view.md Options table, routing description, and Examples section -- APM operating principle requires a CHANGELOG entry for every user-facing behavior change. view.md omits --registry [NAME] from Options and its routing description still implies a lockfile entry is required. Two file edits; primary conversion surface for registry-cohort upgraders and the clearest pre-merge gap.

  2. [auth-expert] Add local-path early-return to _is_explicit_git_form (guard on ./, ../, / prefixes or dep_ref.is_local) -- apm view ./local-pkg versions with a default registry silently dispatches registry credentials for a nonsensical query. dep_ref.is_local is available; the fix is one line and closes a real auth-misfire gap before this reaches production registry users.

  3. [cli-logging-expert + devx-ux-expert + performance-expert] Capture _effective_default_registry result and thread it into _display_registry_versions; emit logger.info routing announcement before the auto-route call -- Three personas independently converge on the silent routing gap. The performance-expert's capture-and-thread refactor is the structural prerequisite that makes the announcement trivially correct and eliminates a redundant lockfile read -- one change delivers source disclosure, the perf fix, and closes the UX gap.

  4. [python-architect] Delegate _effective_default_registry to registry_wiring (add get_effective_default_registry_for_path(project_root: Path)) to eliminate feature-gate drift risk -- The two implementations diverge on user-fallback behavior. If registry_wiring's feature-gate logic changes, the fix will not propagate to view. A delegation is the correct long-term fix; small enough for a scoped follow-up issue.

  5. [test-coverage-expert] Add unit test for --registry UNKNOWN_NAME error path; add integration-with-fixtures test for default-registry routing with a real apm.yml and patched RegistryClient -- The unknown-registry error path is completely dark (error message and exit code unverified). The integration-tier gap means the core PR promise is exercised only with triple-mocked internals, below the tier floor for CLI command surface changes.

Architecture

classDiagram
    direction LR
    class view_module {
        <<Module>>
        +display_versions(package, logger, project_root, registry)
        +_display_registry_versions(package, dep_ref, logger, registry_name)
        +_is_explicit_git_form(package) bool
        +_effective_default_registry(project_root) Optional~str~
    }
    class registry_wiring_module {
        <<Module>>
        +get_effective_default_registry(data) Optional~str~
        +should_skip_github_probe_for_dep(dep_ref, default) bool
        +routes_unscoped_to_registry(dep) bool
    }
    class config_loader_module {
        <<Module>>
        +resolve_effective_registries(regs, default) tuple
    }
    class feature_gate_module {
        <<Module>>
        +is_package_registry_enabled() bool
    }
    class APMPackage {
        <<ValueObject>>
        +registries Optional~dict~
        +default_registry Optional~str~
        +from_apm_yml(path) APMPackage
    }
    class DependencyReference {
        <<ValueObject>>
        +source Optional~str~
        +parse(dep_str) DependencyReference
    }
    view_module ..> config_loader_module : resolve_effective_registries
    view_module ..> feature_gate_module : is_package_registry_enabled
    view_module ..> APMPackage : from_apm_yml
    view_module ..> DependencyReference : parse
    registry_wiring_module ..> config_loader_module : resolve_effective_registries
    registry_wiring_module ..> feature_gate_module : is_package_registry_enabled
    classDef touched fill:#fff3b0,stroke:#d47600
Loading
flowchart TD
    A[apm view PKG versions] --> B{marketplace ref?}
    B -- yes --> C[display marketplace plugin]
    B -- no --> D[DependencyReference.parse]
    D --> E{--registry passed?}
    E -- yes --> F[_display_registry_versions\nregistry_name=value or None]
    F --> R1([return])
    E -- no --> G[effective_root = project_root or cwd]
    G --> H{apm.yml exists?}
    H -- yes --> I[_lookup_lockfile_ref]
    I --> J{locked source\n== registry?}
    J -- yes --> K[_display_registry_versions]
    K --> R2([return])
    J -- no --> L
    H -- no --> L[_is_explicit_git_form?]
    L -- False --> M[_effective_default_registry\nfeature gate + apm.yml read]
    M --> N{default registry\nconfigured?}
    N -- yes --> O[_display_registry_versions]
    O --> R3([return])
    N -- no --> P
    L -- True --> P[GitHubPackageDownloader\nlist_remote_refs]
    P --> Q[render refs table]
Loading

Recommendation

The routing fix is correct, read-only, and consistent with the apm install precedent. No blocking security findings. Three items should land in this PR before merge: (1) CHANGELOG.md entry + view.md update -- non-negotiable per APM operating principle; (2) local-path guard in _is_explicit_git_form -- closes a real auth-misfire gap; (3) logger.info routing announcement with result-capture refactor -- closes the source-disclosure gap raised by three independent panelists. Once those three are in, the PR is mergeable. The _effective_default_registry delegation to registry_wiring, the integration-tier test, and the unknown-registry unit test should follow as scoped issues.


Full per-persona findings

Python Architect

  • [recommended] _effective_default_registry duplicates feature-gate logic from registry_wiring and diverges on user-fallback behavior at src/apm_cli/commands/view.py:485
    registry_wiring.get_effective_default_registry already owns this contract. The two functions diverge on user-fallback path. Drift risk: a feature-gate change in registry_wiring will not propagate to view.
    Suggested: Add get_effective_default_registry_for_path(project_root: Path) to registry_wiring.py and delegate from view.py.

  • [recommended] No comment explaining why routes_unscoped_to_registry is not used at routing step 3 at src/apm_cli/commands/view.py:589
    DependencyReference.parse() does NOT set source='git' for explicit URL forms -- using routes_unscoped_to_registry would silently break the git-URL escape hatch. This constraint is invisible without a comment.

  • [nit] _pr is a cryptic 3-char alias; rename to effective_root at src/apm_cli/commands/view.py:578

  • [nit] explicit = registry_name or None is redundant double-normalization at src/apm_cli/commands/view.py:384

CLI Logging Expert

  • [recommended] Auto-route to default registry (case 3) emits no [i] routing announcement at src/apm_cli/commands/view.py:589
    display_versions silently routes a plain shorthand to the registry. Output table changes from Name/Type/Commit to Version/Published with no indication of why. A logger.info should announce the routing decision.
    Suggested: logger.info(f"Routing to registry '{_effective_default_registry(_pr)}' (use a git URL to force git path)") before the _display_registry_versions call.

  • [nit] Help example comment column breaks alignment on the --registry NAME line at src/apm_cli/commands/view.py:655

  • [nit] (known: ...) in registry error is informal; prefer (available: ...) at src/apm_cli/commands/view.py:390

  • [nit] 'bare' in --registry option help is CLI slang; prefer 'without a value' at src/apm_cli/commands/view.py:683

DevX UX Expert

  • [recommended] --registry flag is silently dropped when the versions field is omitted at src/apm_cli/commands/view.py:706
    apm view org/repo --registry myreg (without versions) falls silently through to local-metadata output with no hint the flag was ignored.
    Suggested: Guard: if registry is not None and field != 'versions': logger.warning("--registry is only valid with the 'versions' field")

  • [recommended] view.md Options table and commands.md skill guide not updated with --registry [NAME] at docs/src/content/docs/reference/cli/view.md:52

  • [recommended] Silent routing change to registry produces no source disclosure in output at src/apm_cli/commands/view.py:589
    Same command produces Version/Published on a machine with a default registry and git refs on clean CI. No indication why.

  • [recommended] view.md versions description is stale -- still says lockfile is required for registry routing at docs/src/content/docs/reference/cli/view.md:41

  • [recommended] Bare --registry form adds no value over auto-routing; deviates from npm/pip/cargo required-value idiom at src/apm_cli/commands/view.py:676

  • [nit] Help example --registry # From the default registry is misleading once auto-routing is live at src/apm_cli/commands/view.py:654

Supply Chain Security

  • [nit] User-supplied --registry NAME echoed verbatim in error message without repr() quoting at src/apm_cli/commands/view.py:390
    Suggested: logger.error(f"Registry {explicit!r} is not configured (known: {known})")

  • [nit] SCP form without username (host:path, no @) not detected as git form; routes to registry at src/apm_cli/commands/view.py:481
    _is_explicit_git_form requires BOTH @ AND :. github.com:org/repo returns False. Harmless (produces a 404 from registry) but confusing.

  • [nit] Silent except Exception: pass in _effective_default_registry swallows apm.yml parse errors with no diagnostic at src/apm_cli/commands/view.py:516
    Suggested: Log at debug level before returning None.

OSS Growth Hacker

  • [recommended] No CHANGELOG entry for a user-facing behavior change that resolves a prominent registry-user pain point at CHANGELOG.md
    Suggested: Add under [Unreleased] Fixed: "apm view org/repo versions with a default registry configured now routes to the configured registry for unlocked shorthands instead of failing with a git auth error. --registry [NAME] added for explicit control. (feat(view): route 'view versions' to the registry when a default is configured #1938)"

  • [recommended] docs/reference/cli/view.md does not reflect the new --registry flag or the default-registry routing behavior at docs/src/content/docs/reference/cli/view.md

  • [nit] preview-and-validate.md describes view versions as listing only git tags -- now incomplete for registry producers at docs/src/content/docs/producer/preview-and-validate.md

  • [nit] Help comment Remote tags/branches (or registry) buries the new registry path for registry-first users at src/apm_cli/commands/view.py

Auth Expert

  • [recommended] _is_explicit_git_form does not classify local filesystem paths as git forms; causes registry auth to fire for local-path arguments at src/apm_cli/commands/view.py:478
    apm view ./local-pkg versions with a default registry returns False from _is_explicit_git_form, triggering step 3 and dispatching registry credentials for a nonsensical query. dep_ref.is_local is available as a clean guard.
    Suggested: if p.startswith('./') or p.startswith('../') or p.startswith('/'): return True

  • [nit] CLI help example claims git URL 'forces the git path' but only when --registry is absent at src/apm_cli/commands/view.py:654
    When --registry is passed with a full git URL, registry routing fires first. The advertised escape-hatch semantics do not hold in the combined case.

Doc Writer

  • [recommended] reference/cli/view.md Options table missing --registry [NAME] at docs/src/content/docs/reference/cli/view.md:54
    Suggested: | --registry [NAME] | List versions from a registry. Bare uses lockfile/default; NAME forces a named registry. |

  • [recommended] reference/cli/view.md versions routing description is stale after routing fix at docs/src/content/docs/reference/cli/view.md:41
    Still implies lockfile entry is required; step-3 routing (default registry + unlocked shorthand) is not mentioned.

  • [recommended] reference/cli/view.md Examples section missing --registry usage and git-URL escape hatch at docs/src/content/docs/reference/cli/view.md:56

  • [recommended] CHANGELOG.md [Unreleased] block missing entries for routing fix and new --registry flag at CHANGELOG.md:8

  • [nit] commands.md view entry missing --registry [NAME] in options column at packages/apm-guide/.apm/skills/apm-usage/commands.md:21

Test Coverage Expert

  • [recommended] --registry UNKNOWN_NAME error path has no test at tests/unit/test_view_command.py
    Every existing --registry test mocks _display_registry_versions before the error branch is reached. Error message and exit code are both dark. Probed: zero hits in test file for 'unknown', 'not configured', 'registry_not_found'.
    Suggested: test_view_versions_unknown_registry_name_exits_with_error: mock registries dict without 'nonexistent', assert exit_code==1 and 'not configured' in output.
    Proof (missing at unit): tests/unit/test_view_command.py::test_view_versions_unknown_registry_name_exits_with_error -- proves: apm view pkg versions --registry unknown-name exits 1 and names the missing registry in the error

  • [recommended] Default-registry routing tested only at unit tier; no integration-with-fixtures coverage at tests/integration/test_wave6_outdated_view_coverage.py
    Core promise tested exclusively at unit tier with triple-mocked internals. Tier-floor for CLI command surface is integration-with-fixtures.
    Proof (missing at integration-with-fixtures): tests/integration/test_wave6_outdated_view_coverage.py::TestViewVersionsRegistryRouting::test_shorthand_routes_to_registry_when_default_configured -- proves: apm view myorg/myrepo versions in a project with a configured default registry calls the registry API, not git

  • [nit] _is_explicit_git_form .git-suffix branch is untested at tests/unit/test_view_command.py
    URL and SCP forms are exercised indirectly; .git suffix has no test. Probed: zero hits for .git suffix in test file.
    Proof (missing at unit): tests/unit/test_view_command.py::test_view_versions_dot_git_suffix_forces_git_even_with_default_registry -- proves: apm view owner/repo.git versions routes to git even when a default registry is configured

Performance Expert

  • [recommended] _effective_default_registry result is discarded; _display_registry_versions re-runs resolve_effective_registries and re-reads lockfile at src/apm_cli/commands/view.py:589
    Step 3 calls _effective_default_registry as a boolean guard then discards the result. _display_registry_versions then reruns resolve_effective_registries and does a second LockFile.read. Fixable with one change: capture and pass as registry_name=.
    Suggested: _default_reg = None if _is_explicit_git_form(package) else _effective_default_registry(_pr); if _default_reg: _display_registry_versions(package, dep_ref, logger, registry_name=_default_reg); return

  • [nit] apm.yml is_file() stat issued twice on same path at src/apm_cli/commands/view.py:508

  • [nit] LockFile.read has no cache; pre-existing double-read pattern inherited by step-3 path at src/apm_cli/commands/view.py

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

Generated by PR Review Panel for issue #1938 · 737.6 AIC · ⌖ 15.8 AIC · ⊞ 5.5K ·

@github-actions github-actions Bot removed the panel-review Trigger the apm-review-panel gh-aw workflow label Jun 28, 2026
@nadav-y nadav-y added the panel-review Trigger the apm-review-panel gh-aw workflow label Jun 28, 2026
@github-actions github-actions Bot mentioned this pull request Jun 28, 2026
@danielmeppiel

Copy link
Copy Markdown
Collaborator

apm-review-panel advisory -- feat/view-versions-registry-routing

Panel run: inline (9 personas + CEO synthesis)
Stance: ship_with_followups
Copilot inline review: 3 findings (all LEGIT, all resolved in 9cd9ae8 by author)


Orchestrator reservations addressed

Reservation Addressed by
Feature must remain feature-gated; _effective_default_registry must honor is_package_registry_enabled() Confirmed: Copilot finding #3487548406 (LEGIT, resolved in 9cd9ae8); TestEffectiveDefaultRegistry class verifies gate short-circuits before registry resolution
Registry-routing decision must be auditable (logs chosen route + git-URL escape hatch) Confirmed: routing precedence logged via CommandLogger at each branch; git-URL override tested in test_view_versions_explicit_git_url_forces_git_even_with_default_registry
~255 lines of added tests must exercise routing-choice branches and escape hatch Confirmed: 6 routing-branch tests plus SCP and explicit-git-URL escape-hatch tests in TestViewCommand; additional direct coverage of _display_registry_versions error paths added in this fold

Copilot inline review classification

id file finding verdict disposition
3487548393 view.py _is_explicit_git_form only detected git@ SCP prefix; arbitrary SSH usernames missed LEGIT Resolved in 9cd9ae8 (detects any user@host:path pattern)
3487548406 view.py _effective_default_registry() not honoring is_package_registry_enabled() feature gate LEGIT Resolved in 9cd9ae8
3487548421 test_view_command.py No test for bare --registry Click option parsing LEGIT Resolved in 9cd9ae8 (test_view_versions_bare_registry_flag_forces_registry added)

Panel follow-up disposition (fold-vs-defer)

# source item decision notes
FU-1 test-coverage-expert Direct tests for _display_registry_versions body (4 error paths unmocked) FOLDED TestDisplayRegistryVersions class added in a6ecffa with 4 tests: unknown registry name, no registry configured, RegistryError propagation, happy-path output
FU-2 devx-ux-expert Warn when --registry supplied without versions field FOLDED Guard added in view() in a6ecffa: logger.warning("--registry is only valid with the versions field; flag ignored")
FU-3 python-architect Extract _effective_default_registry to shared helper in install/registry_wiring.py DEFERRED Scope boundary: refactoring to share with install/registry_wiring.py crosses a module boundary into the install pipeline; not within this PR's routing-addition scope. File a follow-up issue.
FU-4 devx-ux-expert Update commands.md skill resource with --registry [NAME] flag FOLDED packages/apm-guide/.apm/skills/apm-usage/commands.md updated in a6ecffa
FU-5 doc-writer Deduplicate registry-routing description in view.md FOLDED Description bullet now forward-references the subcommand paragraph (canonical routing description kept in subcommand section) in a6ecffa

Lint evidence (fold commit a6ecffa)

ruff check src/ tests/     -- All checks passed
ruff format --check        -- 1319 files already formatted
pylint R0801               -- 10.00/10 (no duplication)
lint-auth-signals.sh       -- [+] auth-signal lint clean

CI evidence

  • Pre-fold CI on 648b02d8: ALL GREEN (Lint, Build & Test Shard 1+2, Coverage, CodeQL, APM Self-Check, PR Binary Smoke, Spec conformance, Merge Gate)
  • Fold commit a6ecffab7: CI not scheduled (expected -- PR is DIRTY/CONFLICTING; merge-commit path blocked until Phase 6 rebase)
  • Local lint chain fully green on fold commit

Mergeability snapshot

field value
head_sha a6ecffa
mergeable CONFLICTING
merge_state_status DIRTY
notes needs rebase against current main (handled by Phase 6 conflict-resolution subagent)

Panel personas

python-architect, cli-logging-expert, devx-ux-expert, supply-chain-security-expert, oss-growth-hacker, auth-expert, doc-writer, test-coverage-expert, performance-expert (active=false; no hot path touched)

Shepherd-driver loop complete. Ready-to-merge pending Phase 6 rebase.

nadav-y and others added 4 commits June 28, 2026 21:55
…onfigured

`apm view <pkg> versions` only consulted the lockfile to decide registry vs
git, so an unlocked shorthand fell through to `git ls-remote` even when a
default registry was configured -- inconsistent with `apm install`, which
routes unscoped shorthands to the default registry.

Routing precedence in display_versions (highest first):
  1. --registry [NAME] -- force the registry path (named, or default if bare).
  2. lockfile records the package as source: registry (existing behavior).
  3. a default registry is configured and the ref is a plain shorthand
     (mirrors `apm install`); an explicit git URL stays on the git path.

Adds the --registry [NAME] flag for explicit control and keeps a full git URL
as the escape hatch to force git. _display_registry_versions already resolved
the default registry for unlocked packages; it now also honors an explicit
registry name (clear error when unknown). All paths are read-only -- no
install or lockfile mutation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- _is_explicit_git_form now detects SCP-style refs for any SSH user
  (e.g. alice@github.com:org/repo), not just git@, plus .git suffixes.
  Arbitrary-user SCP refs no longer mis-route to the default registry.
- _effective_default_registry honors the registries experimental feature
  gate (is_package_registry_enabled), mirroring install's
  get_effective_default_registry -- a config.json default no longer routes
  view->registry when registries are disabled.
- Tests: bare --registry parses and forces the registry path; SCP git ref
  routes to git; feature-gate-off returns no default registry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add local-path early-return to _is_explicit_git_form so ./local-pkg,
  ../path, and /abs/path are treated as git forms and never dispatch
  registry credentials for a nonsensical query (auth-expert finding)
- Capture _effective_default_registry result at step 3 and thread it as
  registry_name to _display_registry_versions, eliminating the redundant
  re-read inside that function; emit logger.info routing announcement so
  users can tell why they got registry results instead of git refs
  (cli-logging-expert + devx-ux-expert + performance-expert finding)
- Add CHANGELOG [Unreleased] Added entry for routing fix and --registry flag
- Update docs/reference/cli/view.md: routing description, Options table
  with --registry [NAME], and new Examples entries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix stale subcommand section in view.md: 'installed registry packages'
  implied only locked deps could use registry listing; updated to describe
  the three-signal routing (--registry flag, lockfile source, default
  registry for plain shorthands) so the doc matches the implementation
- Add unit test test_view_versions_unknown_registry_name_exits_with_error:
  patches resolve_effective_registries to return a dict without the
  requested name and asserts exit 1 with 'not configured' in output;
  the error path was previously untested
- Add integration tests TestViewVersionsRegistryRouting in test_view_coverage.py:
  test_registry_flag_routes_to_named_registry exercises the real Click
  command with an apm.yml fixture, mocking only external I/O; verifies
  the version table is printed; test_registry_flag_unknown_name_exits_one
  covers the same error path at integration tier

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@danielmeppiel danielmeppiel force-pushed the feat/view-versions-registry-routing branch from a6ecffa to 2991d2e Compare June 28, 2026 19:57
@danielmeppiel

Copy link
Copy Markdown
Collaborator

Rebased onto current main at cdc0495 -> 2991d2e.

Conflicting paths resolved (faithful merge of both intents):

  • CHANGELOG.md

Lint contract: uv run --extra dev ruff check src/ tests/ and uv run --extra dev ruff format --check src/ tests/ both silent post-rebase.

Post-push mergeability: gh pr view --json mergeStateStatus,mergeable reports BLOCKED / MERGEABLE. Push used git push --force-with-lease=feat/view-versions-registry-routing:a6ecffab7c087a16134ecf863b234c934ff87eb1 nadav-y HEAD:feat/view-versions-registry-routing (--force-with-lease, never bare --force). BLOCKED state is expected: fork CI runs require maintainer Approve-and-run; conflict is resolved.

Ready for maintainer review.

…sts, and doc fixes

- Warn when --registry is used without the versions field (previously silently
  ignored); addresses devx-ux panel follow-up.
- Add TestDisplayRegistryVersions with 4 direct tests covering: unknown
  registry name, no-registry-configured, RegistryError propagation, and
  happy-path output; addresses test-coverage-expert follow-up.
- Deduplicate registry-routing description in view.md: Description bullet
  now forward-references the subcommand paragraph; addresses doc-writer
  follow-up.
- Update commands.md skill resource to expose --registry [NAME] for view;
  addresses devx-ux follow-up on apm-usage skill drift.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danielmeppiel danielmeppiel force-pushed the feat/view-versions-registry-routing branch from 2991d2e to 8bf45fd Compare June 28, 2026 20:03
@danielmeppiel danielmeppiel merged commit 9aaeecf into microsoft:main Jun 28, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

panel-review Trigger the apm-review-panel gh-aw workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants