You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(install): honor saved targets across MCP and LSP (#2414)
* fix(install): share effective target across integrations
Honor CLI, manifest, and saved target precedence once across package, MCP, and LSP phases. Fail required unresolved or unwritable service integrations instead of skipping with success.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(install): fold target review follow-ups
Preserve diagnostics on required failures, clarify target help, type the canonical decision, and cache immutable projections.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fold second review panel feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Repair target preflight test contracts
Extract no-work handling to preserve the pipeline module budget and make phase-focused tests select a target explicitly.
apm-spec-waiver: Restores existing effective-target precedence without extending the OpenAPM contract.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Extract MCP and LSP reconciliation
Keep install.py within the enforced source budget while preserving one shared target decision and command-owned failure rendering.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fold final target review findings
Align target usage exits, update diagnostics, architecture guards, agent guidance, and self-audit hashes after the final convergence pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix cowork target phase fixtures
Model the newly typed target_decision field explicitly so cowork gating tests exercise the unresolved-decision path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Resolve target rebase semantics
Preserve the certified effective-target owner, alias exclusions, provenance typing, and unified guide while retaining the latest main behaviors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix MCP helper compatibility after rebase
Keep fail-on-write strictness opt-in for direct helper callers while production integration continues to pass it explicitly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: danielmeppiel <danielmeppiel@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
16
`docs/src/content/docs/specs/openapm-v0.1.md`.
17
17
(by @sergio-sisternes-epam, #2365)
18
18
- Package-declared targets now restrict dependency primitive deployment without expanding project or consumer authorization, preventing Claude-only hooks from leaking into Cursor and repairing stale owned entries on update; the contract is cited in `docs/src/content/docs/specs/openapm-v0.1.md`. By @sergio-sisternes-epam (#2362)
19
+
- Saved targets from `apm config set target` now drive package, MCP, and LSP
20
+
phases in `apm install` and `apm update`; unresolved or failed required
21
+
service writes exit non-zero with a next step instead of silently succeeding.
22
+
(reported by @ryodocx, #2414, closes #2345)
23
+
19
24
- Copilot hook packages with JavaScript scripts no longer fail with "hooks: hooks must be an object"; APM keeps generated `package.json` and nested JSON bundle assets out of project `.github/hooks/scripts/` and user `~/.copilot/hooks/scripts/`, where Copilot's recursive hook-loader scan would reject them as descriptors; use `.mjs` for ES module scripts targeting Copilot or VS Code. (#2322)
20
25
-`apm uninstall` now accepts the portable `_local/<name>` key printed by
21
26
`apm deps list` and rejects missing or ambiguous batches with a nonzero status
@@ -103,6 +108,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
103
108
`apm install --target intellij`: APM writes the plugin-read config path,
104
109
migrates only APM-owned entries from the obsolete data path, and preserves
105
110
user-authored entries in both files. (closes #2344) (by @xalvarez, #2410)
111
+
- Saved targets from `apm config set target` now drive package, MCP, and LSP
112
+
phases in `apm install` and `apm update`; unresolved or failed required
113
+
service writes exit non-zero instead of skipping with success.
114
+
(by @ryodocx, closes #2345)
115
+
106
116
-`apm install --dry-run` no longer lists the project's own `includes: auto`
107
117
self-managed files under "Files that would be removed"; the orphan preview
108
118
now excludes the synthesized lockfile self-entry, matching the real install
Copy file name to clipboardExpand all lines: docs/src/content/docs/reference/cli/config.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -65,7 +65,7 @@ Remove `KEY` from `~/.apm/config.json`. No-op if the key is not set. Supported u
65
65
| Key | Type | Default | Description |
66
66
| --- | --- | --- | --- |
67
67
|`auto-integrate`| boolean |`true`| Auto-discover `.prompt.md` files under `.github/prompts/` and `.apm/prompts/` and merge them into compiled `AGENTS.md` output. |
68
-
|`target`| target token | unset | Default target for installs when `--target` and `apm.yml target(s)` are absent. Uses the same parser as `apm install --target` (single or comma-separated). |
68
+
|`target`| target token | unset | Default target for package, MCP, and LSP phases of `apm install` and `apm update` when `--target` and `apm.yml target(s)` are absent. Uses the same parser as `apm install --target` (single or comma-separated). |
69
69
|`self-update.channel`| enum |`stable`| Default release channel for `apm self-update`: `stable` selects the latest stable release; `prerelease` selects the newest non-draft prerelease. Both pass the selected release to the installer as one normalized `VERSION`. `APM_SELF_UPDATE_CHANNEL` overrides config. |
70
70
|`self-update.install-dir`| path | installer default | Default target directory passed to the self-update installer as `APM_INSTALL_DIR`. `APM_INSTALL_DIR` overrides config. |
71
71
|`temp-dir`| path | system temp | Directory used for clone and download operations. Useful when the OS temp directory is locked down (for example, corporate Windows endpoints rejecting `%TEMP%` with `[WinError 5]`). |
Copy file name to clipboardExpand all lines: docs/src/content/docs/reference/cli/install.md
+6-4Lines changed: 6 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,15 +48,15 @@ With no arguments it installs everything from `apm.yml`. With one or more `PACKA
48
48
|---|---|---|
49
49
|`--target`, `-t VALUE`| auto-detect | Force deployment targets. Comma-separated for multiple (`-t claude,cursor`). Values: `copilot`, `claude`, `cursor`, `opencode`, `codex`, `gemini`, `antigravity`, `windsurf`, `kiro`, `intellij`, `vscode`, `agent-skills`, `all`; experimental `copilot-cowork` and `copilot-app` are also accepted when enabled. IntelliJ-specific integration is MCP-only and writes JetBrains Copilot's user-scope MCP config; package file primitives use the Copilot profile. `all` excludes `agent-skills`, `antigravity`, and `intellij`; combine them explicitly to add them, for example `all,intellij`. Explicit MCP target lists are exact: `intellij,claude` writes only those two client configs. See the precedence note below. With nothing to detect, install exits `2` with a teaching message. |
50
50
|`--runtime VALUE`| unset | Legacy alias for `--target` (single value only). Still accepted; prefer `--target`. |
51
-
|`--exclude VALUE`| unset | Skip one runtime from the resolved MCP target set (explicit selection, manifest, or auto-detection). |
51
+
|`--exclude VALUE`| unset | Skip one runtime from the resolved MCP/LSP target set (explicit selection, manifest, saved config, or auto-detection). |
52
52
|`--only apm\|mcp`| both | Install only APM packages or only MCP servers. |
53
53
|`-g`, `--global`| off | Install to user scope (`~/.apm/`) instead of the current project. MCP servers deploy only to global-capable runtimes, such as Copilot CLI, Claude Code, Codex CLI, Gemini CLI, Antigravity CLI, Kiro, Windsurf, and JetBrains Copilot. |
54
54
|`--legacy-skill-paths`| off | Deploy skills to per-client paths (`.cursor/skills/`, `.github/skills/`, ...) instead of the converged `.agents/skills/`. Env: `APM_LEGACY_SKILL_PATHS=1`. |
55
55
56
56
File primitives resolve targets in this order: `--target`, manifest
57
57
`targets:`, `apm config set target ...`, then auto-detection. MCP resolves
58
-
`--runtime` / `--target`, then manifest targets, then machine discovery only
59
-
when the manifest is unrestricted.
58
+
`--runtime` / `--target`, then manifest targets, saved config, then
59
+
auto-detection only when `apm.yml` declares no targets.
60
60
61
61
### Policy and trust
62
62
@@ -112,6 +112,8 @@ in `apm.yml`, then run `apm install` again.
112
112
113
113
-**Auto-bootstrap.**`apm install <pkg>` with no `apm.yml` creates a minimal one. Bare `apm install` with no `apm.yml` exits with a hint to run `apm init` or `apm install <org/repo>`.
114
114
-**Target persistence on bootstrap.** When `--target` maps to recognized manifest targets, those target(s) are persisted to the new manifest's `targets:` field so a later bare `apm update` redeploys to the same targets without re-specifying `--target`.
115
+
-**One effective target.** Package primitives, MCP servers, and LSP servers consume one target decision per invocation: `--target` > `apm.yml targets:` > `apm config set target ...` > auto-detect. A saved target therefore applies to `apm install`, `apm install --mcp`, and later `apm update` runs without another flag.
116
+
-**Required service writes fail loudly.** If MCP or LSP work is declared but no target can be resolved, install exits non-zero before changing the manifest, package deployment, or native service config. A native MCP/LSP config write failure also exits non-zero with the failed target and a permissions/path next step. A successful direct `--mcp` add never reports `Install interrupted`.
115
117
-**Diff-aware.** Packages whose ref or version changed in `apm.yml` are re-downloaded automatically. MCP servers with matching config are skipped (`already configured`); changed config is re-applied (`updated`).
116
118
-**MCP-only lock state.** A normal project install creates or updates `apm.lock.yaml` when `apm.yml` declares only MCP dependencies, records the resolved MCP configs and targets, and migrates a legacy `apm.lock` first. Repeating the same install leaves the lockfile and target configs byte-identical. If initial lock creation fails, install exits nonzero and warns with writable-directory and rerun guidance.
117
119
-**Lockfile replay and Git ref freshness.** Plain and `--frozen` installs may trust `apm.lock.yaml` and the local Git cache, reusing the locked commit for unchanged Git dependencies across the full resolved graph. In contrast, `apm install --update`, `apm install --refresh`, [`apm update`](../update/) with or without `--force`, [`apm lock --update`](../lock/), and [`apm outdated`](../outdated/) establish mutable Git refs from upstream instead of accepting stale refs from a local bare Git cache. APM picks up upstream changes to a transitive package's `apm.yml` only when you regenerate the graph -- run `apm update` or `apm lock --update`. See the [lockfile specification](../../lockfile-spec/) for the replay contract.
@@ -213,7 +215,7 @@ apm install owner/skill-bundle --skill '*' # reset to all skills
213
215
| Code | Meaning |
214
216
|---|---|
215
217
|`0`| Success. All requested dependencies and local content deployed. |
216
-
|`1`| Install failure: security scan blocked a critical finding, auth error, manifest write error, dependency resolution error, `--frozen` with a missing lockfile or a direct dependency absent from `apm.lock.yaml`, any reported install error (the diagnostic summary closes with `Installation failed with N error(s)`), or unhandled exception. `--force` does **not** suppress general install errors. The diagnostic summary names the cause. |
218
+
|`1`| Install failure: security scan blocked a critical finding, auth error, manifest or required MCP/LSP config write error, dependency resolution error, `--frozen` with a missing lockfile or a direct dependency absent from `apm.lock.yaml`, any reported install error (the diagnostic summary closes with `Installation failed with N error(s)`), or unhandled exception. `--force` does **not** suppress general install errors. The diagnostic summary names the cause. |
217
219
|`2`| Usage error: no deployment target detectable (no `--target`, no `target(s):` in `apm.yml`, no default target configured via `apm config set target <value>`, and no harness signal in the project), `--ssh` and `--https` both passed, `--frozen` and `--update` both passed, `--root` combined with `--global`, or a Click flag conflict. |
Copy file name to clipboardExpand all lines: docs/src/content/docs/reference/cli/update.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,7 +45,7 @@ For a read-only install that pins to whatever is already in `apm.lock.yaml` -- t
45
45
|`--global`, `-g`| off | Refresh user-scope dependencies under `~/.apm/` instead of the current project (mirrors `apm install -g`). |
46
46
|`--force`| off | Overwrite locally-authored files and deploy despite critical security findings. It does not change ref freshness: update still requires current upstream refs. Use only after independent verification. |
47
47
|`--parallel-downloads N`|`4`| Max concurrent package downloads. `0` disables parallelism. |
48
-
|`--target TARGET`, `-t TARGET`|auto-detect | Agent harness(es) to update for. Accepts a single value (`claude`, `copilot`, `cursor`, `windsurf`, `kiro`, `codex`, `opencode`, `gemini`) or comma-separated list (`--target claude,cursor`). Overrides`apm.yml targets:`and auto-detection. |
48
+
|`--target TARGET`, `-t TARGET`|resolution chain | Agent harness(es) to update for. Accepts the same target values and comma-separated lists as [`apm install --target`](../install/#target-selection). Resolution is `--target` >`apm.yml targets:`> `apm config set target ...` > auto-detect. |
49
49
50
50
## Examples
51
51
@@ -102,6 +102,8 @@ apm update
102
102
-**No partial consent.** A single prompt covers both revision-pin manifest rewrites and the normal update plan; declining leaves everything unchanged.
103
103
-**`--dry-run` skips the prompt.** It computes and prints the plan, including revision-pin SHA/tag rewrites, but never writes and never asks.
104
104
-**Target contraction is reconciled.** A successful update removes unchanged dependencies' deployed files, lockfile ownership, and merge-hook config/sidecar entries for targets no longer declared in `apm.yml`, even when no dependency ref changes -- same contract as [`apm install`'s target-contraction note](../install/#notes); see [Hooks and commands](../../../producer/author-primitives/hooks-and-commands/#hooks) for what the merge-hook config/sidecar files are.
105
+
-**One target decision covers services.** The effective target used for package deployment is reused for MCP and LSP reconciliation. Saved config targets are not re-detected or dropped after package updates. Required native config failures exit non-zero.
106
+
-**No-op and service-only repair.** An accepted update with no dependency ref changes still reconciles missing MCP/LSP config. A manifest with only MCP/LSP dependencies also uses `apm update` as a configuration repair pass; `--dry-run` previews this without writing.
105
107
-**Empty caches are restored.** If the lockfile expects dependencies but `apm_modules/` has no materialized packages, an otherwise unchanged update restores the cache from the same refs and reports `Restored dependency cache without changing refs.` No confirmation is required because dependency refs do not move.
106
108
107
109
## Back-compat: `apm update` used to be the self-updater
0 commit comments