fix(mcp): honour per-dep registry URL during install (#1393)#1443
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes MCP installation so that a dependency’s per-entry registry: URL in apm.yml is actually used during install-time server resolution, instead of being stored but ignored.
Changes:
- Group MCP registry-resolved dependencies by
dep.registryand instantiateMCPServerOperations(registry_url=...)per unique registry URL. - Extract
_install_registry_group()to encapsulate the validate -> fetch -> overlay -> install loop for one registry group. - Remove the “registry not yet applied” overlay warning and update/add unit tests to validate the new routing behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| tests/unit/integration/test_mcp_per_dep_registry.py | Adds coverage for per-dependency registry grouping and routing behavior (but currently includes non-ASCII characters in docstrings/comments). |
| tests/unit/integration/test_mcp_integrator.py | Updates overlay warning expectations so registry: <url> no longer emits a warning. |
| src/apm_cli/integration/mcp_integrator.py | Removes the warning previously emitted for dep.registry overlay strings. |
| src/apm_cli/integration/mcp_integrator_install.py | Implements per-dependency registry URL routing by grouping deps and running installs per registry group. |
e67246b to
776ddc9
Compare
APM Review Panel:
|
| Persona | B | R | N | Takeaway |
|---|---|---|---|---|
| Python Architect | 0 | 1 | 2 | Clean helper extraction with correct grouping logic; 13-param signature is tolerable at this scope but operations: Any loses type safety unnecessarily. |
| CLI Logging Expert | 0 | 2 | 1 | Heartbeat repeats per-group without naming the registry; users with 2+ registries see duplicated lines with no way to tell them apart. |
| DevX UX Expert | 0 | 1 | 2 | Per-dep registry install promise delivered; error path leaks misleading guidance when URL is invalid; search hint points at wrong registry. |
| Supply Chain Security Expert | 0 | 1 | 1 | Per-dep registry URL passes through existing scheme validation (https-only default); no token leakage. Recommend adding allowed_registries policy gate as hardening follow-up. |
| OSS Growth Hacker | 0 | 2 | 1 | Strong community-contributor signal; per-dep registry routing unlocks a compelling enterprise story angle worth a release beat and a docs example. |
| Auth Expert | 0 | 0 | 1 | Per-dep registry routing is auth-neutral: SimpleRegistryClient uses bare requests.Session with no Authorization headers, so no token leakage on arbitrary URLs. |
| Doc Writer | 0 | 2 | 1 | No stale "ignored" claim in user docs (field was already documented), but CHANGELOG entry and an apm-guide example are missing for a now-honoured field. |
| Test Coverage Expert | 0 | 1 | 2 | Unit regression-trap for per-dep registry routing exists but no integration-with-fixtures test proves the end-to-end install path honours registry: URL. |
B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.
Top 6 follow-ups
- [Doc Writer] Add CHANGELOG [Unreleased] Fixed entry framing per-dep registry routing as enterprise capability unlock (closes [BUG] apm install ignores dependencies.mcp[].registry #1393). -- Three panelists converge (devx-ux, oss-growth, doc-writer). Silent release-comms drift otherwise; evaluators scan CHANGELOG for enterprise signals.
- [Doc Writer] Add per-dep
registry: <url>example toapm-guide/dependencies.mdandconsumer/install-mcp-servers.md. -- Feature is invisible without docs example. Two panelists converge (oss-growth, doc-writer). Agent-facing apm-guide is authoritative for LLM consumers. - [DevX UX Expert] Wrap
MCPServerOperations(registry_url=...)intry/except ValueErrorwith actionable error pointing at theapm.ymldep, notMCP_REGISTRY_URLenv var. -- Invalid per-dep URL currently surfaces misleading guidance or raw traceback. One try/except delivers correct error ergonomics. - [CLI Logging Expert] Disambiguate heartbeat and success lines per registry group (verbose-mode registry annotation). -- Users with 2+ registries see duplicated output with no way to tell groups apart. Progressive-disclosure fix: verbose annotation only.
- [Test Coverage Expert] Add integration-tier test proving
apm installroutes deps to per-dep registry URL (mock only HTTP layer). -- Unit regression trap exists but integration tier is missing on a portability-by-manifest surface. Elevates above typical nit per evidence weighting. - [Supply Chain Security Expert] Add optional
allowed_registriespolicy field toMcpPolicyfor enterprise registry lockdown. -- No urgency (apm.yml trust boundary already allowscommand:arbitrary code) but completes the governed-by-policy story for enterprise adopters.
Architecture
classDiagram
direction LR
class MCPIntegrator {
<<BaseIntegrator>>
+install(mcp_deps, ...)
+_apply_overlay(cache, dep)
+_detect_mcp_config_drift(deps, configs)
+_install_for_runtime(rt, deps, ...)
}
class run_mcp_install {
<<ModuleFunction>>
+run_mcp_install(mcp_deps, ...) int
}
class _install_registry_group {
<<ExtractedHelper>>
+_install_registry_group(operations, ...) int
}
class MCPServerOperations {
<<Service>>
+__init__(registry_url)
+validate_servers_exist(names)
+batch_fetch_server_info(servers)
}
class SimpleRegistryClient {
<<Adapter>>
+__init__(registry_url)
}
class MCPDependency {
<<ValueObject>>
+name str
+registry str or None or False
+is_self_defined bool
}
run_mcp_install ..> _install_registry_group : delegates per group
run_mcp_install ..> MCPServerOperations : constructs per registry URL
_install_registry_group ..> MCPServerOperations : calls validate/fetch/install
_install_registry_group ..> MCPIntegrator : calls static helpers
MCPServerOperations *-- SimpleRegistryClient : owns
run_mcp_install ..> MCPDependency : reads registry field
class _install_registry_group:::touched
class run_mcp_install:::touched
classDef touched fill:#fff3b0,stroke:#d47600
flowchart TD
A["apm install"] --> B["MCPIntegrator.install delegates"]
B --> C["run_mcp_install"]
C --> D{"Split: self_defined vs registry deps"}
D -->|self_defined| E["_install_self_defined_servers"]
D -->|registry| F["Group deps by dep.registry URL"]
F --> G{"For each group_registry_url"}
G --> H["MCPServerOperations(registry_url=group_url)"]
H --> I["_install_registry_group helper"]
I --> J["operations.validate_servers_exist"]
J --> K{"invalid?"}
K -->|yes| L["raise RuntimeError"]
K -->|no| M["check + drift detection"]
M --> N["batch_fetch_server_info"]
N --> O["apply_overlay per dep"]
O --> P["install_for_runtime per rt"]
P --> Q["configured_count += 1"]
G -->|next group| H
Recommendation
Merge after adding the CHANGELOG entry (highest-confidence panel consensus, can land in same PR). The docs example and ValueError handling are strong fast-follows worth filing as issues immediately post-merge. The contributor did clean work -- warm merge comment naming the enterprise unlock will reinforce the contributor funnel.
Full per-persona findings
Python Architect
- [recommended]
operations: Anydiscards static type info whenMCPServerOperationsis importable under TYPE_CHECKING atsrc/apm_cli/integration/mcp_integrator_install.py:37
Type hints on all public APIs;MCPServerOperationsis a concrete class. UsingAnyhides the contract from static analysis.
Suggested: Add to TYPE_CHECKING block:from apm_cli.registry.operations import MCPServerOperations; changeAnytoMCPServerOperations. Same forproject_root/console/logger. - [nit] 13-parameter helper could use a grouped context dataclass in a follow-up
Pragmatic follow-up: bundleproject_root/user_scope/verbose/console/logger/target_runtimes/stored_mcp_configsinto a frozenMCPInstallContextdataclass. - [nit]
group_dep_nameslist is redundant withgroup_dep_map.keys()for object deps atsrc/apm_cli/integration/mcp_integrator_install.py:250
Defensible for backward-compat with plain-string deps that lack.name, but worth a one-line comment.
CLI Logging Expert
- [recommended] Heartbeat emitted per-group without registry context -- confusing for multi-registry installs at
src/apm_cli/integration/mcp_integrator_install.py:66
mcp_lookup_heartbeatfires inside_install_registry_group; user with 2 registries sees two identical lines. Newspaper test fails. Verbose-mode annotation 'Looking up 3 MCP servers in https://...' would satisfy progressive disclosure.
Suggested: Passgroup_registry_urlinto helper; when not None, append to heartbeat /verbose_detail. - [recommended] Removed "registry not yet applied" warning replaced with silent acceptance -- missing positive info line for custom registry at
src/apm_cli/integration/mcp_integrator.py
When user explicitly configured a non-default registry URL, should see confirmation it took effect (helps debugging auth/network issues).verbose_detailsatisfies progressive disclosure.
Suggested: Before calling helper:if group_registry_url and verbose: logger.verbose_detail(f'Using custom registry: {group_registry_url}') - [nit] "All registry MCP servers already configured" can repeat per-group without disambiguation at
src/apm_cli/integration/mcp_integrator_install.py:111
Non-rich path emits the success line per group; with two groups up-to-date, user sees same line twice.
DevX UX Expert
- [recommended]
ValueErrorfrom invalid per-dep registry URL surfaces misleading "Check MCP_REGISTRY_URL" guidance or raw traceback atsrc/apm_cli/integration/mcp_integrator_install.py:254
SimpleRegistryClient.__init__raisesValueErrorwith "Check MCP_REGISTRY_URL if set" text, but for a per-depregistry:field the env var is irrelevant.try/exceptonly catchesImportError, soValueErrorpropagates unhandled.
Suggested: WrapMCPServerOperations(registry_url=group_registry_url)intry/except ValueErrorthat emits actionable error pointing atapm.ymldep. - [nit] Recovery hint "apm mcp search " after per-dep registry failure points at default registry, not the failing one at
src/apm_cli/integration/mcp_integrator_install.py:348
Search always hits default; misleading for private-registry users. Out of scope for this bugfix but worth follow-up issue. - [nit] Missing CHANGELOG entry for user-visible behavior change at
CHANGELOG.md
PR removes a user-visible warning and enables a previously-promised feature.
Supply Chain Security Expert
- [recommended] No policy gate restricts which registry URLs MCP deps may target at
src/apm_cli/policy/policy_checks.py
Policy engine checks MCP server names (check 7) but noallowed_registriesequivalent.apm.ymlalready a trust boundary (command:allows arbitrary code), so strictly less dangerous than existing surfaces -- but worth a follow-up enterprise lockdown hook.
Suggested: Add optionalallowed_registries: [...]field toMcpPolicy; when set, reject deps whoseregistry:value does not prefix-match. Unset = backward-compat allow-all. - [nit] Consider logging when a per-dep registry override is active
Diagnostic log line improves auditability in CI.
OSS Growth Hacker
- [recommended] Add a CHANGELOG entry that frames the fix as an enterprise capability unlock, not just a bug fix at
CHANGELOG.md
Enterprise framing converts plumbing-fix into adoption signal for evaluators scanning the changelog.
Suggested: Under Unreleased Fixed: 'MCP per-dep registry routing:registry: https://...on individual MCP deps is now honoured at install time, enabling mixed public+private MCP server topologies. Thanks @sergio-sisternes-epam. (fix(mcp): honour per-dep registry URL during install (#1393) #1443, closes [BUG] apm install ignores dependencies.mcp[].registry #1393)' - [recommended] Consumer docs (
install-mcp-servers.md) only showregistry:false-- add a string-URL example to surface the new capability atdocs/src/content/docs/consumer/install-mcp-servers.md
Enterprise adopters land oninstall-mcp-servers.mdfirst; without an example the feature is invisible.
Suggested: Add a section "Using a private MCP registry" with a 3-lineapm.ymlsnippet showingregistry: 'https://mcp.corp.example.com'alongside a public-registry dep. - [nit] Warm contributor reception in merge comment -- name the enterprise unlock
Improves contributor funnel conversion.
Auth Expert
- [nit] Add explicit
# SECURITY: no auth headers -- registry calls are anonymous by designcomment inSimpleRegistryClientatsrc/apm_cli/registry/client.py:150
Class has no doc/assertion guaranteeing "this session MUST remain unauthenticated". A one-line SECURITY comment would make the invariant grep-discoverable to prevent future contributors from naively addingsession.headers['Authorization'].
Doc Writer
- [recommended] Add an [Unreleased] Fixed entry for per-dep
registry: <url>on MCP deps (closes [BUG] apm install ignores dependencies.mcp[].registry #1393) atCHANGELOG.md
Keep a Changelog + project pattern; PR removes a user-visible warning and makes a documented field functional -- exactly the shape users grep CHANGELOG for. Silent release-comms drift otherwise.
Suggested: Under [Unreleased] Fixed:apm install --mcphonours the per-dependencyregistry: <url>override on MCP deps. (fix(mcp): honour per-dep registry URL during install (#1393) #1443, closes [BUG] apm install ignores dependencies.mcp[].registry #1393) - [recommended]
packages/apm-guide/.apm/skills/apm-usage/dependencies.mdMCP examples omit the per-depregistry: <url>form that this PR makes functional atpackages/apm-guide/.apm/skills/apm-usage/dependencies.md:188
apm-guide is agent-facing source of truth for dependency formats; per repo convention MCP-dep-format changes must update it. Currently strictly behind the manifest-schema doc.
Suggested: Add a 3-line example:registry: https://mcp.internal.example.comon a named MCP dep. - [nit]
docs/src/content/docs/producer/author-primitives/mcp-as-primitive.mdcould mirror the same per-dep URL example for parity atdocs/src/content/docs/producer/author-primitives/mcp-as-primitive.md:68
Field table already documents URL form; examples block omits it.
Test Coverage Expert
- [recommended] No integration-tier test proves
apm installroutes deps to per-dep registry URL end-to-end attests/integration/test_mcp_install_flow.py
New unit tests mockMCPServerOperationsat the class boundary -- they prove grouping logic but not real HTTP routing. Tier floor for install-pipeline is integration-with-fixtures; unit alone does not certify user promise.
Suggested: Add integration test callingrun_mcp_installwithMCPDependency(registry='https://custom.example.com')and assertMCPServerOperationsconstructor received that URL -- mock only HTTP layer beneath.
Proof (missing at):tests/integration/test_mcp_install_flow.py-- proves: When user setsregistry: https://custom.example.comon dep inapm.yml,apm installfetches that dep from the custom registry, not default. [devx, portability-by-manifest] - [nit] Unit regression trap exists for per-dep registry routing (kwarg assertion)
test_single_custom_registry_creates_one_instanceassertsops_cls.call_args == call(registry_url=url)-- valid regression trap at unit tier.
Proof (unknown):tests/unit/integration/test_mcp_per_dep_registry.py::test_single_custom_registry_creates_one_instance-- proves: If someone reverts per-dep registry routing, this test fails. [devx]
assert ops_cls.call_args == call(registry_url=url) - [nit] Self-defined (
registry=False) exclusion test only proves non-pollution, not correct installation
Mocks_check_self_defined_servers_needing_installationto return [] -- self-defined install path is unchanged by this PR and tested elsewhere; noting for completeness.
Proof (unknown):tests/unit/integration/test_mcp_per_dep_registry.py::test_false_registry_deps_are_excluded_from_registry_groups-- proves: Self-defined deps do not pollute registry groups. [devx]
Performance Expert -- inactive
PR touches integration/mcp_integrator_install.py only -- outside the perf-hot-path file set. The per-registry-group serial loop adds O(N) sequential HTTP round-trips where N = distinct registry URLs (typically 1-2); parallelizing groups would shave ~100-300ms per extra registry but is not blocking given common-case N=1.
This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.
Folds the high-confidence panel consensus into the PR: - CHANGELOG [Unreleased] Fixed entry framing per-dep registry routing as enterprise capability unlock (oss-growth + doc-writer + devx-ux converged). - Docs example: 'Using a private MCP registry' in consumer/install-mcp-servers.md; parity examples in producer/ author-primitives/mcp-as-primitive.md and packages/apm-guide/.apm/ skills/apm-usage/dependencies.md. - ValueError wrap on per-dep MCPServerOperations construction: surfaces an actionable error pointing at the apm.yml dep instead of misleading MCP_REGISTRY_URL guidance (devx-ux recommendation). - Integration test in tests/integration/test_mcp_install_flow.py proves a per-dep 'registry: <url>' reaches SimpleRegistryClient at the HTTP layer (test-coverage-expert recommendation; mutation-break gate verified by forcing registry_url=None). - Two pre-existing integration tests still asserted the removed 'not yet applied' warning -- updated to match the documented new behaviour (mirrors test_registry_str_overlay_no_longer_emits_warning). Co-authored-by: sergio-sisternes-epam <sergio.sisternes@epam.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Folds the high-confidence panel consensus into the PR: - CHANGELOG [Unreleased] Fixed entry framing per-dep registry routing as enterprise capability unlock (oss-growth + doc-writer + devx-ux converged). - Docs example: 'Using a private MCP registry' in consumer/install-mcp-servers.md; parity examples in producer/ author-primitives/mcp-as-primitive.md and packages/apm-guide/.apm/ skills/apm-usage/dependencies.md. - ValueError wrap on per-dep MCPServerOperations construction: surfaces an actionable error pointing at the apm.yml dep instead of misleading MCP_REGISTRY_URL guidance (devx-ux recommendation). - Integration test in tests/integration/test_mcp_install_flow.py proves a per-dep 'registry: <url>' reaches SimpleRegistryClient at the HTTP layer (test-coverage-expert recommendation; mutation-break gate verified by forcing registry_url=None). - Two pre-existing integration tests still asserted the removed 'not yet applied' warning -- updated to match the documented new behaviour (mirrors test_registry_str_overlay_no_longer_emits_warning). Co-authored-by: sergio-sisternes-epam <sergio.sisternes@epam.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
c673f5b to
a13b026
Compare
Panel follow-ups folded into the PRMaintainer asked for the high-consensus panel recommendations to land in-PR. All green on Folded (this PR)
Deferred to follow-up issues
Validation
Co-authored-by: @sergio-sisternes-epam for the original fix. |
e5d149f to
3e2d4c5
Compare
3e2d4c5 to
c643846
Compare
) * feat(batch-bug-shepherd): operator visibility + fold-in invariant Refactors the batch-bug-shepherd skill to address two genesis-validated blockers and ship two missing capabilities discovered during a real sweep-all run over 14 microsoft/apm bugs: 1. OPERATOR VISIBILITY (was: silent 30-minute fan-outs) - New asset assets/progress-diagram.md: mermaid template + 5-state palette (pending/active/done/blocked/skipped) + per-phase render rules + dispatch-table contract. - SKILL.md adds 'Operator visibility is a contract' invariant; each phase boundary re-renders the diagram with current-phase coloring and prints a subagent_id -> target dispatch table BEFORE fan-out. - Operator can follow long sagas at a glance instead of waiting in the dark for the next checkpoint. 2. FOLD-IN INVARIANT (was: panel recommendations silently dropped) - assets/verdict-schema.json: shepherd_return gains required recommended_followups[] channel; completion_return gains folded_followups[] + deferred_followups[]; extracted reusable followup_item definition. - assets/shepherd-prompt.md: fixed verdict mapping bug (ship_with_followups + 0 blocking -> ready-to-merge, not needs-author-changes); added recommended_followups extraction step with required source_persona + optional fold_hint tagging. - assets/completion-prompt.md: full rewrite. Adds RECOMMENDED_FOLLOWUPS input; encodes FOLD vs DEFER classifier (FOLD: touches diff / single helper / regression trap / hermetic test / inline comment; DEFER: cross-cutting refactor / new feature / broad doc / architectural addition); per-FOLD item consultation with source_persona + python-architect lens; DEFER items filed as gh issue create tracking issues (never silently dropped); mid-flight reclassify rule to avoid stalls. - SKILL.md adds 'Bias toward folding recommended items' invariant and rewrites Phase 4 spawn contract (9 steps) to thread the recommended_followups channel end-to-end. Eval gate - +3 rubric anchors per content fixture (progress-diagram-header, mermaid-flowchart-rendered, dispatch-table-before-fanout) and +3 invariant anchors (recommended-followups-channel, fold-defer-classifier, tracking-issue-for-defer). - All 12 new anchors MATCH with_skill fixtures and MISS without_skill fixtures (clean value delta). - +3 no-fire trigger items for single-PR fold-in phrasing so the dispatcher will not misfire the batch outer-loop on single-PR fold work (e.g. 'fold the panel recommendations into PR #1234' remains apm-review-panel completion territory). Validation - Schema validates via jsonschema Draft7; accepts new shapes, rejects shepherd_return missing recommended_followups[]. - SKILL.md: 367 lines / 4483 tokens (caps: 500 / 5000). - Description: 965 / 1024 chars; mentions FOLD invariant. - 0 non-ASCII bytes across all modified files. - All 4 changed JSON files parse. Real-task evidence (this skill iteration was driven by a live run) - 5 of 6 in-flight community PRs had their panel recommendations folded in-PR by completion subagents following the new contract, yielding 22 folded items and 8 deferred-to-tracking items across PRs #1387, #1396, #1441, #1443, #1444. The 6th (#1442) is in flight as this lands. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * batch-bug-shepherd: add Phase 5 mergeability gate Adds a post-wave gate that re-probes mergeability for every PR the saga marked ready-to-merge, dispatches one conflict-resolution subagent per CONFLICTING PR, and partitions returns into four post-gate statuses before the final report claims anything is mergeable. Mergeability is post-wave truth, not pre-wave assumption: a PR that Phase 4 marked ready can stop being mergeable the moment the maintainer lands another PR onto main. Without this gate the report ships stale ready claims. Design driven through the genesis skill end-to-end (steps 1-6 handoff packet, steps 7a-7b coder pass, step 8 validation): - NEW Phase 5 (mergeability gate) between completion (Phase 4) and renamed final report (Phase 5 -> Phase 6). - Sub-phases 5a probe (read-only, single-thread, gh pr view --json mergeStateStatus), 5b fan-out (one conflict-resolution subagent per CONFLICTING PR), 5c trust-but-verify re-probe + four-way partition (resolved / requires-author-action / requires-human-judgment / resolution-failed). - NEW assets/conflict-resolution-prompt.md spawn body for 5b. Encodes rebase, faithful merge of both intents, mutation-break re-check, lint silent, --force-with-lease push, re-probe, resolution-confirmation comment. - NEW references/mergeability-gate.md load-on-demand orchestrator step-by-step (load trigger: WHEN ENTERING PHASE 5). Keeps SKILL.md under 5000-token budget. - Schema extends verdict-schema.json oneOf with conflict_resolution_return; --force-with-lease enforced via regex pattern guard on push_command field; bare --force rejected. Five rejection cases validated. - Two-comment-per-PR cap as new architecture invariant: at most one completion-confirmation (Phase 4) + one resolution-confirmation (Phase 5b) per PR. - Progress diagram extended with WAVE4 subgraph (P5a/P5b/P5c), skipped-state semantics, P5b dispatch table requirement. - Final report extended with three new partition sections plus a RESOLUTION CONFIRMATION COMMENT block and mergeability-gate disciplines line. - Evals: +3 content rubric anchors (mergeability-probe-cli, force-with-lease-on-push, post-wave-partition-columns) + 1 optional anchor (two-comment-cap); +1 fire + 2 no-fire trigger items; fixture diff shows the gate firing on a sweep with 2 conflicting PRs and the without-skill failure mode (stale ready claim). SKILL.md: 388 lines / 4867 tokens (budget 500/5000). ASCII only. CI lint pair silent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(bbs): add Phase 1.5 strategic-alignment gate + PRINCIPLES.md Adds a new wave between Phase 1 (triage) and Phase 2 (PR-in-flight cross-reference) that checks every LEGIT bug against the project's rejection contract before spending shepherd / fix / completion work on it. What changes: - NEW PRINCIPLES.md at repo root: 7 numbered principles encoding the project's hard nos (P1 no invented frontmatter; P2 multi-harness with traction gating; P3 vendor neutral; P4 UX floor is not a trade) plus 3 supporting principles (P5 portability; P6 reliability over magic; P7 community over feature count). Bound to apm-ceo + bbs Phase 1.5 + apm-triage-panel + apm-review-panel as the rejection contract. - NEW bbs Phase 1.5 strategic-alignment gate (WAVE 1.5): - one apm-ceo subagent per LEGIT row, in parallel - 4-state verdict: aligned | aligned-with-reservations | out-of-scope | wrong-direction - schema-validated returns; FAILS OPEN on infrastructure failure (malformed-x2 or non-citable principle) so legit bugs are never silently demoted under gate breakage - ABORTS only when apm-ceo.agent.md or PRINCIPLES.md itself is missing (operator-actionable error) - demoted rows flip to status triaged-deferred and SKIP Phase 2/3/4/5; surface in Phase 6 under 'Recommend close as out-of-scope' partition - aligned-with-reservations rows stay in saga; downstream phases surface the reservations in review prose - deferred-PR strategic-rejection comment subagent (S7+S4+A9) posts a courtesy comment on any open PR whose underlying issue was demoted, using the would-be Phase-4 completion-comment slot (two-comments-per-PR cap preserved) - Verdict schema extended with 5th oneOf member strategic_alignment_return (kind, issue, verdict, cited_principle, rationale, reservations). - Ground-truth table grows two columns (strategic_verdict + strategic_rationale) and one status value (triaged-deferred). - Progress diagram inserts P15 between P1 and P2; dispatch-table contract extends to Phase 1.5. - Final-report template adds 'Recommend close as out-of-scope' partition and 'Aligned with reservations' surfacing section. - 2 new fire trigger evals + 1 no-fire (PRINCIPLES.md authoring guard) + 1 new rubric anchor on the three-issues-mixed scenario. Genesis design artifact lives in the session plan store; SKILL.md body remains within 500-line / 5000-token budget (406 lines / 4943 tokens after trimming pre-existing verbose passages on operator-visibility, mergeability, fold-in, composition, and operating-contract sections to make room). 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>
PR #1443 honours per-dep registry URLs at install time, so the warning that said the field would be ignored was removed from _apply_overlay but the matching test still expected it, failing Shard 2 of CI. Flip the test to assert that no warning is emitted, matching the new behaviour. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Description
When an MCP dependency in
apm.ymlspecifies a per-depregistry:URL, APM now uses that URL for server resolution instead of the global default. Previously, the field was stored but ignored with a "not yet applied" warning.Fixes
Fixes #1393
Type of change
Changes
_install_registry_group()helper inmcp_integrator_install.py— encapsulates the validate-fetch-overlay-install loop for a group of registry depsdep.registryURL — deps with per-dep registry URLs get their ownMCPServerOperations(registry_url=url)instance_apply_overlay()test_registry_str_overlay_emits_warningnow verifies no warning is emittedTesting
test_mcp_per_dep_registry.py(grouping, routing, mixed deps)