Skip to content

Commit e94af4a

Browse files
chore: release v0.16.0 (#1526)
Bump pyproject.toml to 0.16.0 (and uv.lock). Move [Unreleased] to [0.16.0] - 2026-05-28 in CHANGELOG.md with one concise 'so what' entry per PR merged since v0.15.0. Minor bump (not patch) is required: the cycle carries a BREAKING change to apm install exit-code semantics plus new user-facing features (apm deps why, semver ranges on git deps, require_pinned_constraint policy, OpenAPM v0.1 spec). Lint mirror green locally (ruff check + format, pylint R0801, auth-signals). Post-merge: tag v0.16.0 to trigger the release workflow. Co-authored-by: danielmeppiel <danielmeppiel@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 080bb02 commit e94af4a

3 files changed

Lines changed: 22 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.16.0] - 2026-05-28
11+
1012
### Added
1113

12-
- OpenAPM v0.1 normative specification at `docs/src/content/docs/specs/openapm-v0.1.md`, JSON Schemas for manifest/lockfile/policy, and conformance fixture seed tree under `tests/fixtures/spec-conformance/` (#1502).
13-
- `batch-bug-shepherd` skill: refactored to a single shepherd-driver convergence loop that closes four production gaps surfaced by the in-flight bug-queue sweep. (1) Fold-by-default recommendation loop -- every panel CEO follow-up and Copilot inline review item is run through `assets/fold-vs-defer-rubric.md` and folded unless it crosses the PR's stated scope. (2) Copilot PR review address loop -- Phase X.0 fetches `copilot-pull-request-reviewer[bot]` review per `assets/copilot-classification-prompt.md`, classifies each item LEGIT/NOT-LEGIT (2-round cap), and folds LEGIT into the same iteration. (3) Post-push CI verification loop -- `gh pr checks --watch` after every push, with `assets/ci-recovery-checklist.md` bucketing failures (lint / test / infra / unknown) under a 3-iteration cap. (4) Orchestrator ownership signal -- assigns the shepherd actor and applies `status/shepherding` on pickup; the label is cleared on terminal state. New `assets/shepherd-driver-prompt.md` replaces the old shepherd-and-completion split. New step X.8 captures a per-PR mergeability snapshot via `gh pr view --json mergeable,mergeStateStatus,statusCheckRollup`; the snapshot lands in the PR advisory comment and is aggregated by the orchestrator into a saga-end mergeability status table (PR, head SHA, CEO stance, outer iterations, folds, deferrals, Copilot rounds, CI status, mergeable, mergeStateStatus, notes) defined in `assets/final-report-template.md` and constrained by the extended `assets/verdict-schema.json` completion-return shape. Validated on the wave-2 shepherd run that drove PRs #1472, #1512, #1513, #1514, #1515, #1516 to advisory-terminal -- PR #1514 hit 4 outer iterations with 11 folds + 1 deferral. (#1518)
14-
- Deterministic Artifactory boundary probe: at install time, `_resolve_artifactory_boundary` HEAD-probes the candidate archive URLs and rebuilds the dependency reference at the proxy-verified split. Covers both explicit-FQDN (`host/artifactory/key/owner/repo/...`) and bare-shorthand-under-proxy deps. Distinguishes "missing repo" from auth (401/403) errors; uses `allow_redirects=False` so the bearer token can't leak cross-host. Mirrors the native GitLab probing pattern but without a separate metadata API. (#1472)
15-
- `ref:` on git-source dependencies now accepts semver ranges (`^1.2.0`, `~1.4`, `>=2.0 <3`, `1.5.x`). `apm install` runs `git ls-remote`, picks the highest tag matching the range, and pins the resolved tag, commit SHA, version, and original constraint in `apm.lock.yaml`. Subsequent installs replay the lockfile without network; use `apm install --update` to re-resolve against current remote tags. Two tag patterns are tried in order (`v{version}`, `{name}--v{version}`) with a bare `{version}` fallback. (closes #1488)
16-
- `apm deps why <package>` explains why a transitive dependency is installed by walking the lockfile's `resolved_by` chain back to the user's direct declaration in `apm.yml`. Supports `--global` for user-scope lockfiles and `--json` for scriptable output (JSON to stdout, all logs to stderr; analogue of `npm why` / `yarn why`). Exits `0` on success, `1` when the package isn't installed or the query is ambiguous, `2` when no lockfile exists. (#1490)
14+
- OpenAPM v0.1 normative spec at `docs/src/content/docs/specs/openapm-v0.1.md` with JSON Schemas for manifest/lockfile/policy and conformance fixtures under `tests/fixtures/spec-conformance/`, so third-party integrators can build conformant tools without reading the rest of the APM docs. (closes #1502, #1517)
15+
- `ref:` on git-source dependencies now accepts semver ranges (`^1.2.0`, `~1.4`, `>=2.0 <3`, `1.5.x`). `apm install` resolves the highest matching remote tag and pins the resolved tag, SHA, and constraint in `apm.lock.yaml`; subsequent installs replay offline, `apm install --update` re-resolves. (closes #1488, #1496)
16+
- `apm deps why <package>` explains why a transitive dependency was installed by walking the lockfile back to your direct declaration in `apm.yml`. Supports `--global` and `--json`; analogue of `npm why` / `yarn why`. (#1495)
17+
- `policy.dependencies.require_pinned_constraint: true` bans unbounded version ranges across `apm.yml`, blocking accidental drift in governed environments. (#1494)
18+
- Deterministic Artifactory boundary probe at install time, so nested GitLab group/subgroup repos behind a JFrog proxy install correctly via the bare-shorthand form (previously failed with HTTP 404). Auth errors (401/403) are now distinguishable from missing-repo errors, and bearer tokens cannot leak cross-host via redirect. (#1472)
1719

1820
### Changed
1921

20-
- **BREAKING:** `apm install` now exits `1` whenever the diagnostic summary reports `Installation failed with N error(s)`. Previously the command exited `0` even after reporting errors, so CI could not detect failure via exit code. `--force` continues to bypass only the security scan's critical-finding block; it does **not** suppress general install errors (matches `npm` / `pip` / `cargo`). Callers that asserted `exit_code == 0` while errors were reported must update.
21-
- Parse-time Artifactory boundary detection no longer uses directory-marker heuristics (`skills/`, `prompts/`, `agents/`, `collections/`, `instructions/`). The install-time resolver is authoritative for the (owner, repo, virtual_path) split. Parse-time defaults differ by mode:
22-
- **Explicit FQDN** (`host/artifactory/key/owner/repo/...`): `parse_artifactory_path` stays intentionally shallow -- `owner` = first segment after the prefix, `repo` = next segment, remainder = `virtual_path`.
23-
- **Bare shorthand under `PROXY_REGISTRY_ONLY`**: `_bare_shorthand_repo_segment_count` defaults to all-as-repo with a structural file-extension rule on the last segment (a path ending in `.prompt.md`/`.instructions.md`/`.chatmode.md`/`.agent.md` is by shape a virtual file; everything before it is the repo).
24-
25-
Both modes converge at install time: `_resolve_artifactory_boundary` HEAD-probes candidate splits and rebuilds the dependency reference at the proxy-verified split. The `_VIRTUAL_PATH_ROOT_SEGMENTS`, `_ARTIFACTORY_VIRTUAL_MARKERS`, and `_ARTIFACTORY_VIRTUAL_FILE_EXTENSIONS` constants are removed. (#1472)
22+
- **BREAKING:** `apm install` now exits `1` whenever the diagnostic summary reports `Installation failed with N error(s)`. Previously it exited `0` even after reporting errors, so CI could not detect failure. `--force` continues to bypass only the security scan's critical-finding block; it does not suppress general install errors (matches `npm` / `pip` / `cargo`). Callers that asserted `exit_code == 0` while errors were reported must update. (#1496)
23+
- Artifactory parse-time boundary detection no longer relies on directory-name heuristics (`skills/`, `prompts/`, `agents/`, `collections/`, `instructions/`); the install-time HEAD probe is now authoritative for the `(owner, repo, virtual_path)` split. Explicit FQDN refs use a shallow `owner/repo` split; bare shorthand under `PROXY_REGISTRY_ONLY` uses a structural file-extension rule. (#1472)
2624

2725
### Fixed
2826

29-
- `install.ps1` Windows installer now works on accounts whose profile directory contains non-ASCII characters (e.g. an accented username). Previously `apm --version` reported `The system cannot find the path specified.` because the generated `apm.cmd` shim baked in an ASCII-mangled path. The shim now embeds the literal `%LOCALAPPDATA%` token (cmd.exe expands at runtime) when the install root lives under the local profile, percent-escapes literal `%` characters in custom `APM_INSTALL_DIR` paths, and carries an advisory `REM` so hand-edits do not re-introduce the bug. The shim is written as ASCII (cmd.exe does not auto-detect UTF-16 .cmd files invoked through PATH, even with a BOM); the `%LOCALAPPDATA%` literal token keeps the embedded target ASCII-safe regardless of the user's profile path encoding. (closes #1509) (#1512)
30-
- `apm install` against `target: opencode` now warns at install time when an agent's frontmatter has shapes OpenCode's Zod schema rejects (`tools:` as list/string instead of `name -> bool` mapping, or `color:` as a non-hex/non-theme value), so users learn why OpenCode refuses to load the agent instead of seeing only a runtime crash. The file is still copied verbatim; a per-target frontmatter transformer is tracked separately. (Phase 1 of #581, #1513)
31-
- `apm compile --target claude` (and the `claude_md` target generally) now honors `compilation.strategy: single-file` and `--single-agents`, collapsing into a single root `CLAUDE.md` instead of silently emitting per-subdirectory `CLAUDE.md` files. Single-file compilation now behaves consistently across all supported targets. (closes #1445) (#1514)
32-
- `apm install git@gitlab.com:owner/repo.git#ref` now succeeds for users with an SSH key and no `GITLAB_APM_PAT` / `GITLAB_TOKEN`. The validator previously ignored the explicit SSH transport on GitLab refs and demanded an HTTPS-token probe, which raised `Authentication failed for gitlab.com / No token available` even though the matching `dependencies.apm` entry in `apm.yml` installed cleanly via SSH. The validation path now mirrors the clone path (and the existing generic-host explicit-ssh arm) and honors `APM_ALLOW_PROTOCOL_FALLBACK=1` with SSH-first ordering. GitLab SSH-key users get the same frictionless install experience GitHub SSH users already had, matching `apm.yml` end-to-end. (closes #1501)
33-
- `apm install -g` now correctly integrates hook JSON files authored in the "naked" Claude settings-slice format (event names at top-level, no outer `hooks:` wrap) into `.claude/settings.json`, `.cursor/hooks.json`, and the copilot per-event layout. Previously the file parsed cleanly but produced an empty merge while the user-facing summary still reported `1 hook(s) integrated`. The integrated-hook counter now only increments for files that actually contributed entries, malformed shapes where `hooks` is not a dict fail closed with a warning, and files that contribute zero entries log a warning instead of silently skipping. (closes #1499) (#1516)
34-
- `apm install` against a registry proxy now works for GitLab nested-group repos (3+ path segments, e.g. `group/subgroup/project`). Previously the proxy resolver guessed `owner/repo` from the first two path segments and treated the rest as an in-repo virtual sub-path, so the downloader requested the wrong archive URL and the install failed with HTTP 404. The new install-time probe HEAD-walks candidate splits against the proxy and locks in the first one whose archive responds, so nested shorthand (`apm install <host>/artifactory/<key>/<group>/<subgroup>/<project>` or the bare-shorthand form under `PROXY_REGISTRY_URL` + `PROXY_REGISTRY_ONLY=1`) just works. The probe distinguishes auth (401/403) from missing-repo (4xx) so a misconfigured token surfaces as an auth problem instead of a "missing repo", and runs with `allow_redirects=False` so the bearer token cannot follow a redirect off the proxy host. When the proxy is unreachable, the `//` notation can mark the repo/virtual boundary explicitly as an escape hatch. (#1472)
35-
- URL-form Artifactory deps no longer round-trip with the `artifactory/<key>` prefix folded into `repo_url`. The duplicated prefix caused the downloader to construct double-prefixed archive URLs (`/artifactory/key/artifactory/key/owner/repo/...`) and 404. `_validate_url_repo_path` now strips the Artifactory VCS prefix before returning the bare `owner/repo` slug; the prefix is still recovered separately via `_extract_artifactory_prefix`. (#1472)
36-
- `apm install --update` now re-resolves direct git-source semver dependencies. Previously, when the dependency's install path already existed on disk, the BFS resolver short-circuited and `--update` was a silent no-op for git-semver refs; the lockfile kept the previously-resolved tag.
37-
- `apm unpack` deprecation banner softened from "will be removed in v0.14" to "will be removed in a future release". The previous wording shipped past v0.14.0 and contradicted reality (the command still ships in v0.15.0). A concrete removal version will be re-stated once a removal milestone is set.
38-
- `policy.dependencies.require_pinned_constraint: true` no longer misclassifies the npm- and cargo-style explicit-equality form `=1.2.3` as `BARE_BRANCH`. Both `1.2.3` and `=1.2.3` are now recognized as pinned constraints; the pip-style `==1.2.3` form is still rejected (not part of node-semver). Follow-up to #1494 / #1505.
39-
- `apm uninstall` now fully cleans `.windsurf/skills/<pkg>/` directories on the `windsurf` target (by @yoelabril, #1486). The deploy path itself will move to `.agents/skills/` per Cascade's native cross-agent discovery -- tracked in #1520.
27+
- `install.ps1` on Windows now works on accounts whose profile path contains non-ASCII characters (e.g. an accented username): the generated `apm.cmd` shim embeds the literal `%LOCALAPPDATA%` token instead of a baked, code-page-mangled path. Previously `apm --version` reported `The system cannot find the path specified.` (closes #1509, #1512)
28+
- `apm.cmd` Windows shim is now written as ASCII so `cmd.exe` parses it correctly when invoked via `PATH`. A previous attempt to write the shim as UTF-16LE broke fresh installs with garbled output and exit code 1. (#1522)
29+
- `install.ps1` is now strict ASCII, so `apm self-update` on `cp1252` Windows consoles no longer crashes with `UnicodeEncodeError: 'charmap' codec can't encode characters`. (#1523)
30+
- `apm install --target opencode` now warns at install time when an agent's frontmatter has shapes OpenCode's Zod schema rejects (`tools:` as list/string, non-hex/non-theme `color:`), so users learn why OpenCode refuses the agent instead of hitting only a runtime crash. (Phase 1 of #581, #1513)
31+
- `apm compile --target claude` now honors `compilation.strategy: single-file` and `--single-agents`, collapsing into one root `CLAUDE.md` instead of silently emitting per-subdirectory files. (closes #1445, #1514)
32+
- `apm install git@gitlab.com:owner/repo.git#ref` now succeeds for users with an SSH key and no `GITLAB_APM_PAT` / `GITLAB_TOKEN`: the validator honors the explicit SSH transport instead of demanding an HTTPS-token probe. GitLab SSH-key users get parity with GitHub SSH users. (closes #1501, #1515)
33+
- `apm install -g` now correctly integrates hook JSON files authored in the "naked" Claude settings-slice format (event names at top-level, no outer `hooks:` wrap). Previously the file parsed cleanly but merged nothing while the summary still reported `1 hook(s) integrated`; the counter now reflects actual contributions and malformed shapes fail closed with a warning. (closes #1499, #1516)
34+
- `apm install --update` now re-resolves direct git-source semver dependencies even when the dependency's install path already exists; previously the BFS resolver short-circuited and `--update` was a silent no-op for git-semver refs. (#1496)
35+
- `policy.dependencies.require_pinned_constraint: true` no longer misclassifies the npm/cargo explicit-equality form `=1.2.3` as `BARE_BRANCH`. Both `1.2.3` and `=1.2.3` are pinned; pip-style `==1.2.3` is still rejected. (follow-up to #1494, #1506)
36+
- `apm uninstall` now fully cleans `.windsurf/skills/<pkg>/` directories on the `windsurf` target. (by @yoelabril, #1486)
37+
- `apm unpack` deprecation banner softened from "will be removed in v0.14" to "will be removed in a future release"; the previous wording shipped past v0.14.0 and contradicted reality. (#1511)
4038

4139
## [0.15.0] - 2026-05-27
4240

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "apm-cli"
7-
version = "0.15.0"
7+
version = "0.16.0"
88
description = "MCP configuration tool"
99
readme = "README.md"
1010
requires-python = ">=3.10"

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)