Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4231d50
feat(install): F5 elapsed time on every exit path (#1116)
May 3, 2026
5e34455
fix(install): F2 do not show '(cached)' for packages downloaded this …
May 3, 2026
a29ff0a
refactor(install): F3 centralise short SHA truncation with hex valida…
May 3, 2026
fe5fa45
feat(install): F1 surface per-dep Resolving heartbeat (#1116)
May 3, 2026
95d86b1
feat(install): F4 surface MCP registry lookup heartbeat (#1116)
May 3, 2026
0013eca
feat(install): F6 per-phase timing in --verbose (#1116)
May 3, 2026
8ce9820
feat(install): F7 parallel level-batched BFS for dep resolution (#1116)
May 3, 2026
f38489c
docs(install): show elapsed time in install summary examples (#1116)
May 3, 2026
3023323
refactor(install): WS2c reframe F7 parallel BFS as central, not featu…
May 3, 2026
e8199fa
feat(install): WS2a in-install repo clone dedup for subdirectory deps…
May 3, 2026
6c646a7
feat(install): WS2b parallel MCP registry batch lookups (#1116)
May 3, 2026
d2ff3ab
feat(install): WS3 persistent two-tier cache for git + HTTP (#1116)
May 3, 2026
9f29270
fix(cache): drop --filter=blob:none from bare clone (#1116)
May 3, 2026
783d188
perf(install): wire persistent cache into whole-repo download path (#…
May 3, 2026
344593c
perf(registry): cache MCP registry GETs with ETag revalidation (#1116)
May 3, 2026
8f26831
fix(install): polish CLI output (#1116)
May 3, 2026
2eb27a6
chore(notice): add filelock attribution to NOTICE (#1116)
May 3, 2026
9db9a18
fix(cache): security and correctness hardening (#1116)
May 3, 2026
1d96078
feat(install): per-dep rendering correctness (#1116)
May 3, 2026
200e304
feat(install): live progress UI for parallel resolution and download …
May 3, 2026
e6df6bd
fix(install): ASCII-only progress bar + complete resolve-phase tasks …
May 3, 2026
cfe1b79
review(install): close defer-show race + document APM_PROGRESS + test…
May 3, 2026
62d3219
merge: resolve install.py conflict from main into PR #1116
May 3, 2026
5e85d74
perf(install): reflink-aware file copies + write-dedup for cache chec…
May 3, 2026
a053441
Merge branch 'main' into perf/install-ux-assessment
danielmeppiel May 3, 2026
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
37 changes: 37 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,43 @@ _Copyright (c) 2014-2026 Anthon van der Neut, Ruamel bvba_

---

## Component. filelock

- Version requirement: `>=3.12`
- Upstream: https://github.com/tox-dev/filelock
- SPDX: `Unlicense`
- Notes: Used for cross-process file-based locks in the persistent install cache.

### Open Source License/Copyright Notice.

_Released into the public domain via The Unlicense (no copyright claimed by upstream)._

```
MIT License

Copyright (c) 2025 Bernát Gábor and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

---

Submitted on behalf of a third-party

The contributions below are identified as submitted on behalf of a
Expand Down
10 changes: 5 additions & 5 deletions docs/src/content/docs/enterprise/policy-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ All examples below use the literal output APM emits today. Symbol legend: `[+]`
$ apm install --verbose
[i] Resolving dependencies...
[i] Policy: org:contoso/.github (cached, fetched 12m ago) -- enforcement=block
[+] Installed 4 APM dependencies, 2 MCP servers
[+] Installed 4 APM dependencies, 2 MCP servers in 1.2s
```

Without `--verbose`, the `Policy:` line is suppressed for `enforcement=warn` and `enforcement=off`. Under `enforcement=block` it is **always** shown (rendered as a `[!]` warning) so users know blocking is active.
Expand All @@ -614,7 +614,7 @@ Same denied dep, but the org policy ships `enforcement: warn`:
```shell
$ apm install
[i] Resolving dependencies...
[+] Installed 4 APM dependencies, 2 MCP servers
[+] Installed 4 APM dependencies, 2 MCP servers in 1.2s

[!] Policy
acme/evil-pkg -- Blocked by org policy at org:contoso/.github -- remove `acme/evil-pkg` from apm.yml, contact admin to update policy, or use `--no-policy` for one-off bypass
Expand All @@ -628,7 +628,7 @@ Violations flow through `DiagnosticCollector` and surface in the end-of-install
$ apm install --no-policy
[!] Policy enforcement disabled by --no-policy for this invocation. This does NOT bypass apm audit --ci. CI will still fail the PR for the same policy violation.
[i] Resolving dependencies...
[+] Installed 4 APM dependencies, 2 MCP servers
[+] Installed 4 APM dependencies, 2 MCP servers in 1.2s
```

#### `APM_POLICY_DISABLE=1` env var: identical wording
Expand All @@ -637,7 +637,7 @@ $ apm install --no-policy
$ APM_POLICY_DISABLE=1 apm install
[!] Policy enforcement disabled by APM_POLICY_DISABLE=1 for this invocation. This does NOT bypass apm audit --ci. CI will still fail the PR for the same policy violation.
[i] Resolving dependencies...
[+] Installed 4 APM dependencies, 2 MCP servers
[+] Installed 4 APM dependencies, 2 MCP servers in 1.2s
```

The warning is emitted on every invocation and cannot be silenced.
Expand Down Expand Up @@ -683,7 +683,7 @@ When a dep brings in an MCP server denied by `mcp.deny` or rejected by `mcp.tran
$ apm install
[i] Resolving dependencies...
[!] Policy: org:contoso/.github -- enforcement=block
[+] Installed 4 APM dependencies
[+] Installed 4 APM dependencies in 0.8s
[x] Transitive MCP server(s) blocked by org policy. APM packages remain installed; MCP configs were NOT written.

[!] Policy
Expand Down
8 changes: 4 additions & 4 deletions packages/apm-guide/.apm/skills/apm-usage/governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ Successful install (verbose) under `enforcement: block`:
$ apm install --verbose
[i] Resolving dependencies...
[i] Policy: org:contoso/.github (cached, fetched 12m ago) -- enforcement=block
[+] Installed 4 APM dependencies, 2 MCP servers
[+] Installed 4 APM dependencies, 2 MCP servers in 1.2s
```

Block: denied dependency aborts the install before integration:
Expand All @@ -226,7 +226,7 @@ Warn: same dep, `enforcement: warn` -- install succeeds, violation flows to summ
```shell
$ apm install
[i] Resolving dependencies...
[+] Installed 4 APM dependencies, 2 MCP servers
[+] Installed 4 APM dependencies, 2 MCP servers in 1.2s

[!] Policy
acme/evil-pkg -- Blocked by org policy at org:contoso/.github -- remove `acme/evil-pkg` from apm.yml, contact admin to update policy, or use `--no-policy` for one-off bypass
Expand All @@ -238,7 +238,7 @@ Escape hatches (`--no-policy` flag and `APM_POLICY_DISABLE=1` env var) emit the
$ apm install --no-policy
[!] Policy enforcement disabled by --no-policy for this invocation. This does NOT bypass apm audit --ci. CI will still fail the PR for the same policy violation.
[i] Resolving dependencies...
[+] Installed 4 APM dependencies, 2 MCP servers
[+] Installed 4 APM dependencies, 2 MCP servers in 1.2s
```

`--dry-run` previews violations (capped at five per severity bucket; overflow collapses):
Expand Down Expand Up @@ -270,7 +270,7 @@ Transitive MCP server blocked -- APM packages stay installed, MCP configs are no
$ apm install
[i] Resolving dependencies...
[!] Policy: org:contoso/.github -- enforcement=block
[+] Installed 4 APM dependencies
[+] Installed 4 APM dependencies in 0.8s
[x] Transitive MCP server(s) blocked by org policy. APM packages remain installed; MCP configs were NOT written.
```

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies = [
"watchdog>=3.0.0",
"GitPython>=3.1.0",
"ruamel.yaml>=0.18.0",
"filelock>=3.12",
]

[project.optional-dependencies]
Expand Down
6 changes: 6 additions & 0 deletions scripts/notice-metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ components:
upstream: https://github.com/ewels/rich-click
spdx: MIT
copyright_snippet: Copyright (c) 2022 Phil Ewels
- name: filelock
pyproject_name: filelock
upstream: https://github.com/tox-dev/filelock
spdx: Unlicense
copyright_snippet: Released into the public domain via The Unlicense (no copyright claimed by upstream).
notes: Used for cross-process file-based locks in the persistent install cache.
- name: watchdog
pyproject_name: watchdog
upstream: https://github.com/gorakhargosh/watchdog
Expand Down
13 changes: 13 additions & 0 deletions scripts/test-integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,19 @@ run_e2e_tests() {
exit 1
fi

# Run cache lockfile-parity test (requires GITHUB_APM_PAT or GITHUB_TOKEN).
# Asserts byte-identical apm.lock.yaml across cold / warm / no-cache
# regimes -- the worst silent regression the cache layer could introduce.
log_info "Running cache lockfile-parity E2E test..."
echo "Command: pytest tests/integration/test_cache_lockfile_parity.py -v -s --tb=short"

if pytest tests/integration/test_cache_lockfile_parity.py -v -s --tb=short; then
log_success "Cache lockfile-parity E2E test passed!"
else
log_error "Cache lockfile-parity E2E test failed!"
exit 1
fi

# Run Azure DevOps E2E tests (requires ADO_APM_PAT)
if [[ -n "${ADO_APM_PAT:-}" ]]; then
log_info "Running Azure DevOps E2E tests..."
Expand Down
16 changes: 16 additions & 0 deletions src/apm_cli/cache/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Persistent content-addressable cache for APM install.

Public API
----------
- :func:`get_cache_root` -- resolve the platform cache directory
- :class:`GitCache` -- content-addressable git repository + checkout cache
- :class:`HttpCache` -- HTTP response cache with conditional revalidation
"""

from __future__ import annotations

from .git_cache import GitCache
from .http_cache import HttpCache
from .paths import get_cache_root

__all__ = ["GitCache", "HttpCache", "get_cache_root"]
Loading
Loading