Skip to content

Commit aded37e

Browse files
feat(copilot-app): hybrid WS-IPC + SQLite project scoping for workflows (#1431)
* deps: add websockets>=12 for Copilot App IPC Required by the hybrid project-scoping path (PR A). When the App is running, APM prefers the localhost WS-IPC surface so workflow rows fire the live WorkflowsChanged broadcast instead of relying on the webview re-reading SQLite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(copilot-app): add project resolver with SQLite fallback New module copilot_app_project.py: frozen dataclasses for RepoContext / ProjectRecipe / ResolvedProject, pure derivers (derive_repo_context, derive_project_recipe), and resolve_or_register_project_sqlite that SELECTs by main_repo_path or INSERTs a fresh row inside BEGIN IMMEDIATE. Race-collision recovery: on sqlite3.IntegrityError, re- SELECT inside the same transaction to return the winning id. Backed by 14 unit tests covering the no-repo / HTTPS / SSH / non- github / subdir-walk-up derive paths and HIT / MISS / external-row / race-recovery / missing-db / schema-too-new resolver branches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(copilot-app): add sync WS-IPC client for live App integration New module copilot_app_ws.py: WsClient context manager using websockets.sync.client (no asyncio in install loop), ws_available() liveness probe bounded to 100ms, and create_project_from_path / create_workflow / update_workflow RPCs. Custom exceptions (WsAppNotRunning / WsAuthError / WsProtocolError) let the caller distinguish silent fallback from warn-and-fallback. Reads ~/.copilot/run/ws.{port,token}, presents Origin: tauri:// localhost (the App rejects any other Origin), and walks past interleaved server push frames to find the response to our request. Permissive JSON parser tolerates unknown / added top-level fields so upstream schema additions don't break us. Backed by 19 unit tests against a real websockets.sync.server harness covering handshake / auth / origin / round-trip / drain / timeout. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(copilot-app): stamp project_id on every workflow row Adds project_id: str | None to WorkflowRow and threads it through both INSERT and UPDATE paths in deploy_workflow. The execution-changed UPDATE includes project_id alongside the other execution fields; the name-only UPDATE also writes project_id so pre-PR-A rows with NULL project_id self-heal on the next install without forcing a content change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(copilot-app): hybrid WS+SQLite dispatch with project scoping prompt_integrator.integrate_prompts_for_target now accepts scope= and forwards user-scope detection to _integrate_prompts_for_copilot_app, which: 1. Parses all candidate workflow-shape prompts up front so the path decision (WS / SQLite / global-warn) is made once per package. 2. Emits a warn-and-proceed diagnostic when --global is combined with workflow-shape prompts, explaining that those workflows will run with CWD=~/.copilot and pointing at the App's Workflows tab to attach them to a project manually. 3. Derives a RepoContext from project_root; when the App is running AND we have a real repo, tries the WS-IPC path first (create_project_from_path + per-workflow create_workflow). On any WsError, warns and falls back to SQLite. 4. SQLite fallback: resolve_or_register_project_sqlite, stamp project_id on every WorkflowRow, suffix display name with ' (<repo>)' so workflows from different repos are distinguishable in the App UI. 5. When the project row was freshly created (was_created=True), emits a one-time restart-the-App info diagnostic referencing the upstream live-refresh gap (github/github-app#5483). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(install): thread scope into integrator dispatch services.py now passes scope= to integrate_*_for_target so the prompt integrator can distinguish project-scope from user-scope at the copilot-app branch. The four sibling integrators (agent, command, hook, instruction) accept scope= as a keyword-only no-op default to keep the call site uniform without changing their behavior. Also refreshes the copilot-app explainer in phases/targets.py to document the PR A auto-register + restart-once UX. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(copilot-app): cover project_id stamping, restart hint, global warn - Extends the seed schema fixture with a projects table so the resolver can run end-to-end. - Asserts on the project-scope roundtrip that the workflow row carries a non-NULL project_id pointing at a projects row with main_repo_path equal to the consumer directory, and that the display name carries the '(<repo>)' suffix. - git init's the consumer directory so derive_repo_context returns a real RepoContext. - Asserts the restart-the-App hint is emitted on the first install into a new repo. - New test_global_install_with_workflow_emits_warning: --global plus workflow-shape prompts warn-and-proceeds (exit 0, row inserted, warning mentions --global + 'attach') instead of the prior hard-fail. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(copilot-app): address panel follow-ups on PR #1431 Path B narrow WS surface (project-registration only), token hardening, fallback regression test, and doc/PR-body honesty pass. Source: - copilot_app_ws.py: delete create_workflow/update_workflow/ WorkflowCreated/_extract_workflow_id; add _scrub_token regex that redacts ?token=... in wrapped exception text; add _token_file_mode_ok check refusing ws.token if group/other-readable (matches App's 0o600 posture); raise WsError from None so library exceptions with the unscrubbed URL are not reachable via __context__. - prompt_integrator.py: rewrite _integrate_prompts_for_copilot_app as a single-loop dispatcher. Resolve project_id once (try WS, fall back to SQLite on WsError; silently swallow WsAppNotRunning and WsAuthError so stale tokens after a restart never warn). Write every workflow row via SQLite with the resolved project_id. One restart- once hint when was_created. Drop the WS/IPC jargon from user-facing wording. Delete _deploy_via_ws. - pyproject.toml + uv.lock: pin websockets>=12,<17. Tests: - tests/unit/integration/test_copilot_app_ws.py: drop TestCreateWorkflow + TestUpdateWorkflow; port TestDrainAndInterleavedPush and TestRecvTimeout onto create_project_from_path; chmod 0o600 in the _write_creds fixture so the new mode check passes; add TestTokenScrub (3) and TestTokenFileMode (3). - tests/integration/test_copilot_app_ws_fallback.py (new): regression trap for WS-error -> SQLite fallback. WsProtocolError mid-deploy still stamps project_id on the workflow row; WsAppNotRunning and WsAuthError stay silent. Docs: - CHANGELOG.md: corrected Unreleased entries (Added/Security). - docs/.../integrations/copilot-app.md: Project scoping + One-time restart hint + --global warn-and-proceed sections. - packages/apm-guide/.apm/skills/apm-usage/commands.md: project-scope + restart-hint + --global warn callouts in the experimental section. PR body: rewritten to drop misleading mode-allowlist bullet and the 'live workflows_changed broadcast' framing; sequence diagram now shows WS for project registration and SQLite for workflow rows; scenario table extended with WS-fallback and token-hardening evidence. Validation: ruff check + format --check silent; 2766 unit integration+install tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor(copilot-app): extract workflow integrator + fold Copilot review nits The copilot-app target deploys *.prompt.md as Copilot App workflow rows (SQLite + optional WS-IPC) instead of files. That path shared NOTHING with the file-based prompt deploy except the source artefact, but it was squatting inside PromptIntegrator (~300 lines of unrelated logic plus its own module-level frontmatter helpers). Extract into a sibling integrator so the file matches how agent_integrator / command_integrator / hook_integrator / instruction_integrator are organised. Refactor: * New src/apm_cli/integration/copilot_app_workflow_integrator.py with CopilotAppWorkflowIntegrator(BaseIntegrator). Inherits BaseIntegrator for find_files_by_glob only -- the file-based collision / link-resolution machinery is irrelevant on the workflow surface (deploy_workflow is an UPSERT keyed on a namespaced id; sync deletes by id from the lockfile). * PromptIntegrator.integrate_prompts_for_target and .sync_for_target keep one trivially small branch per method that delegates to the workflow integrator -- grep copilot-app in prompt_integrator.py and one call site appears for each direction. * Module-level frontmatter helpers (_is_workflow_shape, Schedule, _parse_workflow_frontmatter, _parse_schedule, _derive_package_owner) move with the path that uses them. Re-exported from prompt_integrator for back-compat with tests / external callers. * copilot_app_db / copilot_app_project / copilot_app_ws stay put -- they are already at the right level. Only prompt_integrator was oversized. * Test fixtures unchanged; the integration test that patches copilot_app_ws.WsClient.create_project_from_path still works because the import path did not move. Folded Copilot reviewer nits (PR #1431): * B1: when derive_repo_context(project_root) returns None AND workflow prompts are present AND scope is not user, emit a parallel warn to the existing --global warn. project_id=NULL workflows have the same CWD=~/.copilot pivot risk; the user deserves the same heads-up plus the fix recipe (run inside a git repo or attach from the App UI). * B2: WsClient.create_project_from_path docstring rewritten to match the implementation -- was_created is inferred from the reply type (project_created -> True, project_updated -> False) via _extract_project_fields, not 'always True'. Restart hint only fires on the project_created branch. * B3: _find_repo_root docstring no longer claims symlinks-in-the-chain are blocked. The cheap fix: drop the false claim. The 'right' fix (walk + reject symlinked parents) would break macOS /tmp -> /private/tmp and other legitimate symlinked-ancestor setups, and the threat model (user's own CWD, not adversary input) does not justify the cost. The .git-marker is_symlink() check stays as defence-in-depth. Behavior change: one new warn diagnostic when copilot-app workflows install without a detected git repo. Three pre-existing unit tests in test_copilot_app_error_ux.py updated to filter the new warn out of their per-prompt deploy-error counts (the no-repo warn fires once for the whole install; deploy-error warns are per-prompt). Test gate: 54 targeted + 2766 broad -- all pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(copilot-app): dedupe DB write-prelude + add websockets NOTICE entry - Extract _open_write_txn() helper in copilot_app_db so both deploy_workflow and copilot_app_project.resolve_or_register_project share the missing-DB / version-guard / BEGIN-IMMEDIATE prelude. Closes the pylint R0801 duplicate-code finding without changing behavior or error wording. - Drop the now-unused _connect / _check_user_version / _begin_immediate_with_retry imports from copilot_app_project. - Update test_race_collision_resolves_to_winning_id to patch copilot_app_db._connect (the real entry point) rather than the project module re-export, which is gone. - Add websockets entry to scripts/notice-metadata.yaml and regenerate NOTICE so the drift check passes for the new runtime dependency. 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>
1 parent 66a9a11 commit aded37e

23 files changed

Lines changed: 3024 additions & 394 deletions

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- **Experimental:** `copilot-app` target now scopes workflow rows to a real `projects` row instead of orphaning them at the App's root. When the App is running, project registration goes through the loopback WebSocket IPC surface (`~/.copilot/run/ws.{port,token}`, 0o600) so the project goes through the App's own owner/repo discovery and is immediately known to the webview; when the App is closed, registration falls through to a direct-SQLite `BEGIN IMMEDIATE` resolver against `~/.copilot/data.db`. Workflow rows are always written via SQLite (namespaced ids preserve lockfile stability). `--global` installs that carry workflow-shape prompts now emit a one-time warn-and-proceed diagnostic explaining the CWD-pivot risk and the per-row "attach to project" remediation. A one-time `Restart the Copilot App once` info hint fires on first project registration in a repo (see github/github-app#5483). (#1431)
13+
1014
### Changed
1115

1216
- Unit test coverage raised to 88% (gate: `fail_under = 80`); integration test coverage raised to 71% with first CI gate at 55%. (#1402)
1317

1418
### Fixed
1519

1620
- `apm update` against private Azure DevOps deps no longer fails on Windows with a misleading "az present but not logged in" diagnostic when the user IS signed in via `az login`. Root cause: Python's `subprocess.run(["az", ...])` -> `CreateProcessW` does not honor `PATHEXT` for non-`.exe` executables, so the Windows `az.cmd` wrapper could not be invoked even though `shutil.which("az")` resolved it. `AzureCliBearerProvider` now resolves the `az` binary via `shutil.which` once at construction and passes the absolute path to every subprocess call. As a defense-in-depth measure, the ADO `--update` preflight probe no longer strips `GIT_CONFIG_GLOBAL` / `GIT_CONFIG_NOSYSTEM` / `GIT_ASKPASS`, so Git Credential Manager can answer for Entra-cached ADO credentials whenever bearer acquisition is unavailable for any reason (sandbox, proxy, future PATH quirks). The actual clone path keeps its full gitconfig isolation. (#1430)
17-
1821
- Root `.apm` hooks no longer duplicate after renaming the project directory or using git worktrees; Claude, Codex, Cursor, Gemini, and Windsurf hook configs stay idempotent across checkouts. The hook source-id is now derived from `apm.yml`'s `name` field instead of `install_path.name`, and `apm install` silently heals stale same-content entries from prior checkout basenames. Copilot is unaffected (its hooks live in per-file namespaces under `.github/hooks/`, not a shared merged config). (#1392, closes #1329)
1922

2023
## [0.14.1] - 2026-05-20

NOTICE

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,46 @@ SOFTWARE.
12521252

12531253
---
12541254

1255+
## Component. websockets
1256+
1257+
- Version requirement: `>=12,<17`
1258+
- Upstream: https://github.com/python-websockets/websockets
1259+
- SPDX: `BSD-3-Clause`
1260+
- Notes: Used by the copilot-app integrator to nudge the Copilot desktop App over its local WebSocket IPC channel after writing workflows to the App DB.
1261+
1262+
### Open Source License/Copyright Notice.
1263+
1264+
_Copyright (c) Aymeric Augustin and contributors_
1265+
1266+
```
1267+
Copyright (c) Aymeric Augustin and contributors
1268+
1269+
Redistribution and use in source and binary forms, with or without
1270+
modification, are permitted provided that the following conditions are met:
1271+
1272+
* Redistributions of source code must retain the above copyright notice,
1273+
this list of conditions and the following disclaimer.
1274+
* Redistributions in binary form must reproduce the above copyright notice,
1275+
this list of conditions and the following disclaimer in the documentation
1276+
and/or other materials provided with the distribution.
1277+
* Neither the name of the copyright holder nor the names of its contributors
1278+
may be used to endorse or promote products derived from this software
1279+
without specific prior written permission.
1280+
1281+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1282+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1283+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1284+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
1285+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1286+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1287+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1288+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
1289+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1290+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1291+
```
1292+
1293+
---
1294+
12551295
Submitted on behalf of a third-party
12561296

12571297
The contributions below are identified as submitted on behalf of a

docs/src/content/docs/integrations/copilot-app.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,41 @@ Execution-affecting fields are the prompt body, schedule (`interval` / `schedule
7878

7979
Removing the source `.prompt.md` from a package and re-syncing drops the lockfile entry but does NOT delete the corresponding row from `~/.copilot/data.db` -- it merely orphans it. Run `apm uninstall <pkg>` to remove the row.
8080

81+
## Project scoping
82+
83+
Workflows are scoped to a real Copilot App project so "Run now" in the Workflows tab CWDs into the right repository and the row groups under the correct sidebar entry. APM resolves the project once per install, then stamps every workflow row's `project_id`.
84+
85+
Two resolution paths run in this order:
86+
87+
| Order | When it fires | What it does |
88+
|---|---|---|
89+
| 1 | The Copilot App is running and is reachable on its loopback WebSocket (`~/.copilot/run/ws.{port,token}`, 0o600). | APM calls the App's own `create_project_from_path` over IPC. The App runs full discovery (GitHub owner/repo detection, default branch, account binding) and the resulting project is immediately known to the webview, so opening the Workflows tab cannot hit the white-screen-on-unknown-project failure mode. |
90+
| 2 | The Copilot App is closed, OR the WebSocket surface is unreachable for any reason (stale token after restart, etc). | APM falls back to a direct-SQLite `BEGIN IMMEDIATE` resolver: SELECT by `main_repo_path` (UNIQUE), INSERT if missing. |
91+
92+
In both paths the workflow rows are written via direct SQLite -- the WS surface is currently project-registration only -- so lockfile ids stay namespaced and stable (`apm--<owner>--<pkg>--<prompt>`) across runs and across the WS-vs-SQLite branch.
93+
94+
If APM cannot derive a repo context at all (no `.git/`, no `origin`, etc) the workflows install with `project_id = NULL`. You can attach them to any project after the fact from the App's Workflows tab.
95+
96+
### One-time restart hint
97+
98+
The first time APM registers a brand-new project for a given repository, install prints:
99+
100+
```
101+
[i] Registered a new Copilot App project for this repo. Restart the Copilot App once so the new project appears in the UI (see github/github-app#5483).
102+
```
103+
104+
Subsequent installs into the same repo are silent. The hint is upstream-bug guidance: the App's webview does not currently refresh its projects sidebar when a new `projects` row appears mid-session, so one restart wires the new project into the UI. Once the App learns about the project, neither the install nor the App needs to be restarted again.
105+
106+
## `--global` and workflow-shape prompts
107+
108+
Workflows installed with `apm install --global` run with `CWD=~/.copilot`, not a repository -- which is almost never what the user wants. APM still deploys global workflows (so global skills and commands keep working), but emits a one-time warn-and-proceed diagnostic whenever a `--global` install carries any workflow-shape prompt:
109+
110+
```
111+
[!] Copilot App workflows installed with --global run with CWD=~/.copilot, not a project. Attach the workflow to a project from the App's Workflows tab to fix this, or re-run `apm install` from a repo without --global.
112+
```
113+
114+
The remediation is per-row: attach the workflow to any project from the Workflows tab in the App. Or re-run `apm install` from inside a repo without `--global`.
115+
81116
## Enable and check
82117

83118
Use `apm experimental enable copilot-app` to turn the target on, `apm experimental list` to see all flags, and `apm experimental disable copilot-app` to turn it off again. See the [Experimental flags reference](../../reference/experimental/) for the complete subcommand surface.

packages/apm-guide/.apm/skills/apm-usage/commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ Set `MCP_REGISTRY_URL` (default `https://api.mcp.github.com`) to point all `apm
141141

142142
Use `apm experimental enable copilot-cowork` to turn on Microsoft 365 Copilot Cowork skill deployment. Once enabled, deploy skills with `apm install --target copilot-cowork --global`.
143143

144-
Use `apm experimental enable copilot-app` to turn on GitHub Copilot desktop App workflow deployment. Once enabled, prompts that carry workflow frontmatter -- any flat top-level key of `interval`, `schedule_hour`, `schedule_day` -- can be deployed to the App's SQLite store at `~/.copilot/data.db` with `apm install --target copilot-app` (project scope) or `--target copilot-app --global` (user scope). A `.prompt.md` belongs to exactly ONE surface: workflow-shape prompts go to the App DB, plain prompts go to slash-command targets. Rows always start `enabled = 0` -- you opt in from the App. `apm install / update / uninstall` preserve user state (`enabled`, `last_run_at`, schedule overrides). Override the database path with `APM_COPILOT_APP_DB=<abs-path>`.
144+
Use `apm experimental enable copilot-app` to turn on GitHub Copilot desktop App workflow deployment. Once enabled, prompts that carry workflow frontmatter -- any flat top-level key of `interval`, `schedule_hour`, `schedule_day` -- can be deployed to the App's SQLite store at `~/.copilot/data.db` with `apm install --target copilot-app` (project scope) or `--target copilot-app --global` (user scope). A `.prompt.md` belongs to exactly ONE surface: workflow-shape prompts go to the App DB, plain prompts go to slash-command targets. Rows always start `enabled = 0` -- you opt in from the App. `apm install / update / uninstall` preserve user state (`enabled`, `last_run_at`, schedule overrides). Override the database path with `APM_COPILOT_APP_DB=<abs-path>`. Workflows are scoped to a real Copilot App project: when the App is running APM registers the project over the App's loopback WebSocket so the project is immediately known to the webview; when the App is closed APM falls back to a direct-SQLite `BEGIN IMMEDIATE` resolver. The first install in a brand-new repo prints a one-time "restart the Copilot App once" hint (see github/github-app#5483); subsequent installs are silent. `--global` installs that carry workflow-shape prompts warn-and-proceed because workflows run with `CWD=~/.copilot` rather than a repo -- attach the row to a project from the App's Workflows tab to fix.
145145

146146
### Cross-client skills (`agent-skills`)
147147

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ dependencies = [
3737
"GitPython>=3.1.0",
3838
"ruamel.yaml>=0.18.0",
3939
"filelock>=3.12",
40+
"websockets>=12,<17",
4041
]
4142

4243
[project.optional-dependencies]

scripts/notice-metadata.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,3 +277,9 @@ components:
277277
spdx: MIT
278278
copyright_snippet: Copyright (c) 2014-2026 Anthon van der Neut, Ruamel bvba
279279
notes: Canonical source is SourceForge (Mercurial). LICENSE retrieved from the official PyPI sdist tarball ruamel_yaml-0.19.1.tar.gz.
280+
- name: websockets
281+
pyproject_name: websockets
282+
upstream: https://github.com/python-websockets/websockets
283+
spdx: BSD-3-Clause
284+
copyright_snippet: Copyright (c) Aymeric Augustin and contributors
285+
notes: Used by the copilot-app integrator to nudge the Copilot desktop App over its local WebSocket IPC channel after writing workflows to the App DB.

src/apm_cli/install/phases/targets.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,19 @@ def run(ctx: InstallContext) -> None:
257257
# prevents collisions across projects sharing the same package.
258258
# Rows always arrive enabled=0; users grant the second consent in
259259
# the App's Workflows tab before anything runs on a schedule.
260+
#
261+
# PR A (project-scoping): the integrator now auto-registers a row
262+
# in the App's ``projects`` table for the current repository and
263+
# stamps every workflow with that project_id, so workflows show up
264+
# in the correct project's Workflows tab. On the *first* install
265+
# into a repo, the App's webview does not always live-refresh on
266+
# the externally-inserted ``projects`` row (see github/github-app
267+
# #5483); the integrator emits a one-time restart hint so the user
268+
# is not left wondering why the new project is missing from the UI.
269+
# When the App is running, the integrator prefers the live
270+
# WebSocket-IPC surface so the broadcast fires natively and no
271+
# restart is needed; the SQLite path is the fallback for the
272+
# App-closed case (still the common case during install).
260273

261274
# ------------------------------------------------------------------
262275
# v2 resolution (#1154): signal-based provenance and strict errors.

src/apm_cli/install/services.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ def _format_target_collapse(paths: list[str], verbose: bool) -> tuple[str, list[
272272
force=force,
273273
managed_files=managed_files,
274274
diagnostics=diagnostics,
275+
scope=scope,
275276
)
276277
result["links_resolved"] += _int_result.links_resolved
277278
for tp in _int_result.target_paths:

src/apm_cli/integration/agent_integrator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def integrate_agents_for_target(
9494
force: bool = False,
9595
managed_files: set = None, # noqa: RUF013
9696
diagnostics=None,
97+
scope=None,
9798
) -> IntegrationResult:
9899
"""Integrate agents from a package for a single *target*.
99100

src/apm_cli/integration/command_integrator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ def integrate_commands_for_target(
455455
force: bool = False,
456456
managed_files: set = None, # noqa: RUF013
457457
diagnostics=None,
458+
scope=None,
458459
) -> IntegrationResult:
459460
"""Integrate prompt files as commands for a single *target*.
460461

0 commit comments

Comments
 (0)