Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Removed

- **BREAKING: dropped support for `.collection.yml` / `.collection.yaml` virtual packages.** Dependencies whose paths end in `.collection.yml` or `.collection.yaml` now raise a `ValueError` at parse time with a migration message. Convert any such entry to a regular `apm.yml` with a `dependencies:` section under the same subdirectory, then reference the directory itself as a subdirectory virtual package (no extension). The internal `VirtualPackageType.COLLECTION` enum value, the `download_collection_package` codepath, the `is_virtual_collection()` reference helper, and the `META_PACKAGE` package-type label have been removed -- none were persisted to the lockfile, so existing locks are unaffected. (#1097, closes #1094) Thanks @edenfunf for the original PR.

### Changed

- **Renamed `NOTICE.md` -> `NOTICE`** to follow the Apache / CNCF convention used by upstream third-party-attribution files (e.g. `kubernetes-sigs/kro`, `kubernetes-sigs/headlamp`). The generator (`scripts/generate-notice.py`), `make notice` target, and `NOTICE Drift Check` workflow now operate on the extension-less path. (#1073)
Expand Down
16 changes: 9 additions & 7 deletions docs/src/content/docs/reference/manifest-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ local_path_form = ("./" / "../" / "/" / "~/" / ".\\" / "..\\" / "~\\") path
| `host` | OPTIONAL | FQDN (e.g. `gitlab.com`) | Git host. Defaults to `github.com`. |
| `port` | OPTIONAL | `1`–`65535` | Non-default port on `ssh://`, `https://`, `http://` clone URLs. Not expressible in SCP shorthand. |
| `owner/repo` | REQUIRED | 2+ path segments of `[a-zA-Z0-9._-]+` | Repository path. GitHub uses exactly 2 segments (`owner/repo`). Non-GitHub hosts MAY use nested groups (e.g. `gitlab.com/group/sub/repo`). |
| `virtual_path` | OPTIONAL | Path segments after repo | Subdirectory, file, or collection within the repo. See §4.1.3. |
| `virtual_path` | OPTIONAL | Path segments after repo | Subdirectory or file within the repo. See §4.1.3. |
| `ref` | OPTIONAL | Branch, tag, or commit SHA | Git reference. Commit SHAs matched by `^[a-f0-9]{7,40}$`. Semver tags matched by `^v?\d+\.\d+\.\d+`. |

**Examples:**
Expand Down Expand Up @@ -303,7 +303,7 @@ REQUIRED when the shorthand is ambiguous (e.g. nested-group repos with virtual p
| Field | Type | Required | Pattern / Constraint | Description |
|---|---|---|---|---|
| `git` | `string` | REQUIRED (remote) | HTTPS URL, SSH URL, or FQDN shorthand | Clone URL of the repository. Required for remote dependencies. |
| `path` | `string` | OPTIONAL / REQUIRED (local) | Relative path within the repo, or local filesystem path | When `git` is present: subdirectory, file, or collection (virtual package). When `git` is absent: local filesystem path (must start with `./`, `../`, `/`, or `~/`). |
| `path` | `string` | OPTIONAL / REQUIRED (local) | Relative path within the repo, or local filesystem path | When `git` is present: subdirectory or file (virtual package). When `git` is absent: local filesystem path (must start with `./`, `../`, `/`, or `~/`). |
| `ref` | `string` | OPTIONAL | Branch, tag, or commit SHA | Git reference to checkout. |
| `alias` | `string` | OPTIONAL | `^[a-zA-Z0-9._-]+$` | Local alias. |

Expand All @@ -324,14 +324,16 @@ Local path dependency (development only):

#### 4.1.3. Virtual Packages

A dependency MAY target a subdirectory, file, or collection within a repository rather than the whole repo. Conforming resolvers MUST classify virtual packages using the following rules, evaluated in order:
A dependency MAY target a subdirectory or a file within a repository rather than the whole repo. Conforming resolvers MUST classify virtual packages using the following rules, evaluated in order:

| Kind | Detection rule | Example |
|---|---|---|
| **File** | `virtual_path` ends in `.prompt.md`, `.instructions.md`, `.agent.md`, or `.chatmode.md` | `owner/repo/prompts/review.prompt.md` |
| **Collection (dir)** | `virtual_path` contains `/collections/` (no collection extension) | `owner/repo/collections/security` |
| **Collection (manifest)** | `virtual_path` contains `/collections/` and ends with `.collection.yml` or `.collection.yaml` | `owner/repo/collections/security.collection.yml` |
| **Subdirectory** | `virtual_path` does not match any file, collection, or extension rule above | `owner/repo/skills/security` |
| **Subdirectory** | `virtual_path` does not match any file extension above | `owner/repo/skills/security` |

Classification is by extension only -- never by path segment. A path like `owner/repo/collections/security` (no extension) is **Subdirectory**: the actual on-disk shape (APM package with `apm.yml`, skill bundle, or plugin) is resolved at fetch time by probing for `apm.yml` first.

> **Removed (#1094):** the legacy `.collection.yml` / `.collection.yaml` virtual-package form is no longer supported. Convert any such reference to an `apm.yml` with a `dependencies:` section, then reference the resulting subdirectory as a regular subdirectory virtual package.

#### 4.1.4. Canonical Normalisation

Expand Down Expand Up @@ -527,7 +529,7 @@ dependencies: # YAML list (not a map)
is_virtual: <bool> # True for virtual (file/subdirectory) packages
depth: <int> # 1 = direct, 2+ = transitive
resolved_by: <string> # Parent dependency (transitive only)
package_type: <string> # Package type (e.g. "apm_package", "marketplace_plugin")
package_type: <string> # Package type (e.g. "apm_package", "marketplace_plugin", "meta_package")
content_hash: <string> # SHA-256 of package file tree (e.g. "sha256:a1b2c3...")
is_dev: <bool> # True for devDependencies
deployed_files: <list<string>> # Workspace-relative paths of installed files
Expand Down
8 changes: 5 additions & 3 deletions packages/apm-guide/.apm/skills/apm-usage/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ Virtual packages reference a subset of a repository.
| Type | Detection rule | Example |
|------|---------------|---------|
| File | Ends in `.prompt.md`, `.instructions.md`, `.agent.md`, `.chatmode.md` | `owner/repo/prompts/review.prompt.md` |
| Collection (dir) | Contains `/collections/` (no extension) | `owner/repo/collections/security` |
| Collection (manifest) | Contains `/collections/` + `.collection.yml` | `owner/repo/collections/security.collection.yml` |
| Subdirectory | Does not match file or collection rules | `owner/repo/skills/security` |
| Subdirectory | Does not match a file extension above | `owner/repo/skills/security` |

Classification is by extension only. A path like `owner/repo/collections/security` (no extension) is a Subdirectory; the actual shape -- APM package (incl. dep-only `apm.yml` with no `.apm/`), skill bundle, or plugin -- is resolved at fetch time by probing for `apm.yml`.

> **Removed (#1094):** the legacy `.collection.yml` / `.collection.yaml` virtual-package form is no longer supported. Convert any `.collection.yml` to an `apm.yml` with a `dependencies:` section, then reference the resulting subdirectory as a regular subdirectory virtual package.

## Canonical storage rules

Expand Down
11 changes: 4 additions & 7 deletions src/apm_cli/core/script_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,8 +783,8 @@ def _is_virtual_package_reference(self, name: str) -> bool:

Virtual packages have format:
- owner/repo/path/to/file.prompt.md (virtual file)
- owner/repo/collections/name (virtual collection)
- owner/repo/skills/name (virtual subdirectory/skill)
- owner/repo/collections/name (virtual subdirectory)

Args:
name: Name to check
Expand All @@ -807,10 +807,9 @@ def _is_virtual_package_reference(self, name: str) -> bool:
def _auto_install_virtual_package(self, package_ref: str) -> bool:
"""Auto-install a virtual package.

Handles three types of virtual packages:
Handles two types of virtual packages:
- Virtual files: owner/repo/prompts/file.prompt.md
- Virtual collections: owner/repo/collections/name
- Virtual subdirectories (skills): owner/repo/skills/name
- Virtual subdirectories (skills, collections): owner/repo/skills/name

Args:
package_ref: Virtual package reference
Expand Down Expand Up @@ -845,9 +844,7 @@ def _auto_install_virtual_package(self, package_ref: str) -> bool:

print(f" Downloading from {dep_ref.to_github_url()}")

if dep_ref.is_virtual_collection():
package_info = downloader.download_virtual_collection_package(dep_ref, target_path)
elif dep_ref.is_virtual_subdirectory():
if dep_ref.is_virtual_subdirectory():
package_info = downloader.download_subdirectory_package(dep_ref, target_path)
else:
package_info = downloader.download_virtual_file_package(dep_ref, target_path)
Expand Down
125 changes: 0 additions & 125 deletions src/apm_cli/deps/collection_parser.py

This file was deleted.

Loading
Loading