fix(pack): route empty dependencies bundle (supersedes #2447, closes #2431) - #2458
Merged
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clarify that only dependency mappings select bundle output and prevent null values from regressing to a bundle producer. Addresses the review-panel DevX follow-ups for PR #2447. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fold panel documentation follow-ups so every producer-facing reference distinguishes an explicit empty dependencies mapping from omitted and null declarations. Addresses apm-review-panel follow-ups for #2447. Co-authored-by: danielmeppiel <danielmeppiel@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Daniel Meppiel (danielmeppiel)
requested a review
from Sergio Sisternes (sergio-sisternes-epam)
as a code owner
August 3, 2026 20:05
6 tasks
Copilot started reviewing on behalf of
Daniel Meppiel (danielmeppiel)
August 3, 2026 20:06
View session
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes apm pack output routing so that an explicitly declared empty dependency mapping (dependencies: {}) is treated as intentional and triggers bundle production, while omitted or null dependencies: continues to produce no bundle. It also adds regression coverage and aligns user-facing docs so the three-state contract (omitted vs null vs mapping/empty mapping) is described consistently.
Changes:
- Update
detect_outputs()to selectBundleProducerwhendependenciesis present and non-null (including{}). - Add unit + packaged CLI integration coverage for the empty-mapping and null/omitted behaviors.
- Update reference + producer + agent-facing docs to document the same empty/omitted/null dependency selection rules.
Show a summary per file
| File | Description |
|---|---|
| src/apm_cli/core/build_orchestrator.py | Switch bundle selection from truthiness to an explicit non-null dependencies check; update module docstring to mention {}. |
| tests/unit/core/test_build_orchestrator.py | Add regression tests proving {} selects bundle while null does not. |
| tests/integration/test_pack_root_skills_e2e.py | Add a lifecycle_smoke packaged-CLI test asserting bundle + Copilot plugin manifest are emitted with dependencies: {}. |
| packages/apm-guide/.apm/skills/apm-usage/package-authoring.md | Document the empty-mapping vs omitted/null dependency behavior for bundle production. |
| packages/apm-guide/.apm/skills/apm-usage/commands.md | Update apm pack command reference to explicitly describe {} vs omitted/null behavior. |
| docs/src/content/docs/reference/cli/pack.md | Update CLI reference to state that an empty mapping produces a bundle while omitted/null does not. |
| docs/src/content/docs/producer/repo-shapes.md | Clarify marketplace-only repo shape produces no bundle when dependencies: is omitted. |
| docs/src/content/docs/producer/publish-to-a-marketplace.md | Align marketplace publishing guidance with the explicit-mapping (incl. {}) bundle selection rule. |
| docs/src/content/docs/producer/pack-a-bundle.md | Add a short, explicit note that dependencies: {} selects bundle output and omitted/null does not. |
Review details
- Files reviewed: 9/9 changed files
- Comments generated: 0
- Review effort level: Lite
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(pack): route empty dependencies bundle
TL;DR
apm packnow treatsdependencies: {}as a declared dependency mapping and emits the local bundle. Omitted and nulldependencies:values still do not select bundle output. The packaged CLI lifecycle proves that a Copilot package receives its root skill, bundle, and.github/plugin/plugin.jsontogether.Note
Supersedes #2447 and closes #2431.
Problem (WHY)
dependencies: {}exited successfully but did not create a bundle directory.detect_outputstreated an explicit empty mapping like no declaration.Why this matters: "Grounding outputs in deterministic tool execution transforms probabilistic generation into verifiable action."
Approach (WHAT)
BundleProducerwhendependenciesis non-null, including{}.Implementation (HOW)
src/apm_cli/core/build_orchestrator.py-- replaces the truthiness check with a non-null declaration check at the canonical output-routing boundary.tests/unit/core/test_build_orchestrator.py-- guards empty-mapping routing and null omission semantics.tests/integration/test_pack_root_skills_e2e.py-- invokes the installed CLI withtarget: copilot, an empty mapping, and a root skill; it asserts both build and manifest outputs.{}, bundles; omitted or null does not. The panel fold also removes duplicateapm packcommand rows.Diagrams
Legend: the dashed decision is the changed routing rule; a declared empty mapping now reaches the bundle producer without altering the independent Copilot manifest path.
flowchart LR subgraph Parse[Parse] M["apm.yml"] D["detect_outputs"] end subgraph Produce[Produce] B["BundleProducer"] P["PluginManifestProducer"] end M --> D D -->|"dependencies is not null"| B D -->|"target is copilot"| P B --> S["build skills root-skill SKILL.md"] P --> G[".github plugin plugin.json"] classDef new stroke-dasharray: 5 5; class D new;Trade-offs
is not Noneinstead of truthiness so{}is intentional while omitted and null remain distinct.Benefits
dependencies: {}produces exactly one local bundle directory.skills/root-skill/SKILL.mdin the bundle and.github/plugin/plugin.json.Validation
uv run --extra dev pytest tests/unit/core/test_build_orchestrator.py -q:APM_E2E_TESTS=1 uv run --extra dev pytest tests/integration/test_pack_root_skills_e2e.py::test_pack_empty_dependencies_creates_bundle_and_copilot_manifest -q:Lint and architecture gates
The new empty-mapping regression test failed when the production guard was reverted to the prior truthiness predicate, then passed after restoration.
Scenario Evidence
dependencies: {}can pack its root skill, bundle, and plugin manifest.tests/unit/core/test_build_orchestrator.py::TestDetectOutputs::test_empty_dependencies_mapping_returns_bundle(regression-trap for #2431)tests/integration/test_pack_root_skills_e2e.py::test_pack_empty_dependencies_creates_bundle_and_copilot_manifestdependencies:does not receive a bundle unexpectedly.tests/unit/core/test_build_orchestrator.py::TestDetectOutputs::test_null_dependencies_does_not_return_bundletests/unit/core/test_build_orchestrator.py::TestDetectOutputs::test_neither_block_returns_emptyHow to test
apm.ymlwithtarget: copilotanddependencies: {}; addskills/root-skill/SKILL.mdand an emptyapm.lock.yaml.apm pack --format plugin --verbose; expect exit code 0.build/<name>-<version>/skills/root-skill/SKILL.mdand.github/plugin/plugin.jsonexist.dependencies:value; expect no bundle selection.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com