Skip to content

refactor(core): consolidate red-team lifecycle fixes behind canonical owners#2155

Merged
danielmeppiel merged 91 commits into
mainfrom
apm-rt-arch-c1
Jul 12, 2026
Merged

refactor(core): consolidate red-team lifecycle fixes behind canonical owners#2155
danielmeppiel merged 91 commits into
mainfrom
apm-rt-arch-c1

Conversation

@danielmeppiel

@danielmeppiel danielmeppiel commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

TL;DR

A 3-round internal reliability red-team surfaced 13 defects across MCP config, deployment tracking, install completion, and target capability. Each was fixable in isolation, but the cluster shape pointed at a deeper cause: the same lifecycle invariant was enforced in many places, so a fix in one call site silently drifted from the others. This PR lands all 13 fixes and re-homes them behind four canonical owners so the invariant lives in exactly one place per domain. Owner-invariant tests make the routing structural, not cosmetic.

Single PR by design: it supersedes and closes the 13 point PRs (#2131, #2132, #2133, #2134, #2135, #2141, #2142, #2143, #2144, #2145, #2151, #2152, #2153).

  • +6038 / -1878 across 139 files
  • 4 new canonical owner modules + 3 owner-invariant test suites
  • All required CI green (Lint, both test shards, CodeQL, Spec conformance, gate, build)

Problem (WHY)

The red-team fixed bugs round over round, but the recurrence pattern was the tell: deployment-file ownership, MCP source-of-truth, install exit meaning, and target capability were each computed in several modules. When one call site was patched, the others kept the old behavior — the classic symptom of diffuse ownership in a modular codebase.

This also has to respect APM's boundary discipline. Per PRINCIPLES.md P1:

"APM emits to canonical schemas defined by upstream ecosystems: agentskills.io / Anthropic Claude Skills, GitHub Copilot, Cursor, Windsurf, Codex, Gemini, OpenCode. We do not invent apm-* frontmatter keys, top-level fields, or hidden attributes that downstream consumers must learn to honor APM-ness."

So consolidation must not introduce a harness translation layer. Owners emit each target's native schema directly; they centralize ownership, not abstraction.

Approach (WHAT)

Four canonical owners, one per recurring-bug domain, each guarded by an invariant test that fails if a foreign module reclaims the responsibility:

graph TD
    subgraph Owners["Canonical lifecycle owners"]
        C1["C1 mcp_config_view.py<br/>MCP source-of-truth"]
        C2["C2 deployment_state.py + deployment_ledger.py<br/>deployed-file ownership"]
        C3["C3 target_catalog.py<br/>target capability"]
        C4["C4 install/transaction.py<br/>install completion + exit meaning"]
    end
    audit["audit / install / uninstall"] --> C1
    deploy["install / uninstall / update / compile"] --> C2
    detect["target detection / validation / help"] --> C3
    pipeline["install pipeline / commands.install"] --> C4
    C1 -. owner-invariant .-> INV["structural tests<br/>(regex + AST)"]
    C2 -. owner-invariant .-> INV
    C4 -. owner-invariant .-> INV
Loading

Implementation (HOW)

Cluster Canonical owner Folds (issue)
C1 MCP source-of-truth integration/mcp_config_view.py (327) #2127, #2136, #2149; unifies audit/install/uninstall on one lockfile-bounded current-source view
C2 deployment-file ownership core/deployment_state.py (306) + core/deployment_ledger.py (352) #2129, #2139, #2148; single owner of deployed_files/hashes/local mirrors, additive dual-written ledger
C3 target capability core/target_catalog.py (272) #2138, #2139; target_detection constants become derived projections; KNOWN_TARGETS stays owner of native roots (no translation layer)
C4 install completion install/transaction.py (162) #2126, #2140; InstallDisposition + transactional resolution; commands/install.py is the sole place InstallResult.exit_code maps to process exit

Additional folded fixes that did not need a new owner: hooks top-level version (#2128), compile orphan cleanup on --clean (#2130), parser schema-boundary rejection (#2137), ADO bearer auth preservation in the semver resolver (#2150).

Supporting refactor: extracted the target-specific hook-entry converters into integration/hook_native_formats.py (single owner of native Gemini/Antigravity hook-entry rewriting) — keeps hook_integrator.py under the file-length guardrail and matches the P1 "emit native schema directly" rule.

Owner-invariant tests (the crux)

These prove routing is real, not decorative:

  • tests/unit/core/test_deployment_owner_invariant.py — only the C2 owners + deps/lockfile.py may assign the deployed-file fields.
  • tests/unit/core/test_target_catalog_owner_invariant.py — capability metadata has one source.
  • tests/unit/install/test_install_exit_owner_invariant.py (AST) — only commands/install.py maps InstallResult to a process exit code; no install/ module calls sys.exit.

Trade-offs

  • Additive ledger, one-release wrappers. C2 dual-writes the new ledger alongside existing lockfile fields; a few MCP per-server materializations remain wrapper-backed for one release rather than a hard cutover, to keep the diff reviewable and reversible.
  • Bigger single PR vs. reviewability. Consolidation is only meaningful atomically — splitting owners across PRs would reintroduce the drift window this PR closes. Mitigated by per-cluster commits and the invariant tests.
  • No abstraction layer. Deliberately centralizes ownership without a cross-harness translation type, honoring P1.

Validation evidence

Check Result
CI Lint (ruff, format, yaml, file-length 2100, relative_to, pylint R0801 10.00/10, auth-signals) pass
Build & Test Shard 1 + 2 (Linux) pass
CodeQL (python, actions) pass
Spec conformance gate pass (no waiver required)
gate / build / license-cla pass
Owner-invariant suites (C2/C3/C4) pass
Affected hook integration tests 426 pass

How to test

# owner-invariant crux
uv run --extra dev python -m pytest \
  tests/unit/core/test_deployment_owner_invariant.py \
  tests/unit/core/test_target_catalog_owner_invariant.py \
  tests/unit/install/test_install_exit_owner_invariant.py -q

# full required gate locally
uv run --extra dev python -m pytest tests/unit tests/test_console.py tests/red_team -q -n 4 --dist worksteal

# lint mirror
uv run --extra dev ruff check src/ tests/ && uv run --extra dev ruff format --check src/ tests/ \
  && uv run --extra dev python -m pylint --disable=all --enable=R0801 --min-similarity-lines=10 --fail-on=R0801 src/apm_cli/ \
  && bash scripts/lint-auth-signals.sh

Architecture analysis (onboarding guide)

Written as an onboarding guide for an engineer new to the codebase, reflecting the cured architecture at snapshot cb0964e7a. Produced by a lead architect plus a 10-analyst domain sweep. All 21 architecture and execution-flow diagrams live in a single companion comment: architecture diagram map.

System Overview

APM is a vendor-neutral Python CLI and package manager for AI-agent primitives. Authors declare instructions, skills, prompts, agents, hooks, MCP servers, LSP servers, scripts, dependencies, and target preferences in apm.yml. APM resolves the dependency closure, pins it in apm.lock.yaml, deploys content into native agent-harness layouts, compiles aggregate context files, runs declared workflows, and audits policy or filesystem drift.

The codebase is organized as a layered pipeline:

  1. CLI adaptation parses Click arguments and maps them to application services.
  2. Domain parsing turns apm.yml into APMPackage, dependency references, and primitive models.
  3. Resolution builds a deterministic dependency graph using Git, local, marketplace, or registry sources.
  4. Installation coordinates policy, download, scanning, integration, cleanup, and lockfile phases.
  5. Compilation converts portable instructions into aggregate target context such as AGENTS.md, CLAUDE.md, or GEMINI.md.
  6. Integration writes individual primitives and configuration into native target locations.
  7. Execution compiles referenced prompts and invokes declared scripts or supported runtimes.
  8. Governance checks policy, provenance, content integrity, and replayed deployment drift.

The architecture favors canonical owners:

  • core/target_catalog.py owns target capabilities.
  • core/auth.py owns host classification and credential resolution.
  • deps/apm_resolver.py owns graph resolution.
  • deps/lockfile.py and core/deployment_ledger.py own reproducibility and deployment provenance.
  • install/pipeline.py owns install phase ordering.
  • integration/base_integrator.py and integration/dispatch.py own materialization behavior.
  • core/command_logger.py owns semantic CLI output.
  • policy/ owns governance semantics.
  • cache/ owns persistent Git and HTTP reuse.

The intended lifecycle is:

author -> resolve -> lockfile pins -> install -> compile -> integrate -> run -> drift and policy audit

In the implementation, the updated lockfile is persisted after integration so it can record actual paths, hashes, owners, MCP state, and materialization outcomes.

Diagram reference: System context in the PR architecture comment.

Per-domain deep dives + cross-cutting architecture (click to expand)

CLI surface, command dispatch, and logging UX

The executable is registered as apm_cli.cli:main in pyproject.toml. src/apm_cli/cli.py configures encoding and standard-library logging, defines global options, registers top-level commands, performs update checks, and converts uncaught failures into process exit behavior.

Command modules under src/apm_cli/commands/ are adapters. They parse Click values, discover the project manifest, construct service requests, invoke domain services, and select human or machine output. Command families cover dependency management, compilation, package production, execution, policy, marketplaces, runtime management, caching, and diagnostics.

Important components:

  • src/apm_cli/cli.py: process entry, root Click group, global options, registration, and top-level error handling.
  • src/apm_cli/commands/_helpers.py: manifest discovery, version display, update notification, and shared command helpers.
  • src/apm_cli/core/command_logger.py: semantic output API for progress, lifecycle, auth, policy, install, and cleanup events.
  • src/apm_cli/utils/console.py: Rich, Colorama, and plain-output routing plus ASCII STATUS_SYMBOLS.
  • src/apm_cli/utils/diagnostics.py: thread-safe diagnostic collection and stable category-oriented rendering.
  • src/apm_cli/output/: typed compilation and script-execution presentation models.
  • src/apm_cli/factory.py: registry-backed construction of MCP client and package-manager adapters.

CommandLogger and Python logging are distinct. The former is user-facing and writes through console helpers; the latter is an operational/debug channel. DiagnosticCollector supports collect-then-render behavior so parallel phases can report consistently without printing directly.

Inputs include CLI options, environment variables, the current directory, manifests, lockfiles, and configuration. Outputs include Rich or plain text, JSON or SBOM data, filesystem changes, subprocess execution, and exit status.

Diagram reference: 1. CLI surface, dispatch, and logging UX.

Dependency resolution and lockfile

The dependency domain converts manifest references into pinned packages and a reproducible graph. It supports shorthand Git references, explicit hosts, local paths, monorepo subpaths, registries, marketplaces, VCS proxies, refs, and semver constraints.

Important components:

  • src/apm_cli/models/dependency/reference.py: DependencyReference parsing, canonical identity, transport metadata, refs, virtual paths, and install locations.
  • src/apm_cli/deps/apm_resolver.py: deterministic, level-batched breadth-first dependency resolution.
  • src/apm_cli/deps/dependency_graph.py: tree, flattened map, conflict, and cycle structures.
  • src/apm_cli/deps/github_downloader.py: legacy-named facade over vendor-neutral acquisition strategies.
  • src/apm_cli/deps/host_backends.py: host-specific URL and API behavior.
  • src/apm_cli/deps/transport_selection.py: pure clone-transport planning.
  • src/apm_cli/deps/clone_engine.py: authenticated clone execution and controlled fallback.
  • src/apm_cli/deps/tiered_ref_resolver.py: per-run cache, API, bare-cache, and clone-based ref resolution.
  • src/apm_cli/deps/registry/: package-registry version selection, download, extraction, and integrity verification.
  • src/apm_cli/deps/path_anchoring.py: parent-relative transitive local dependency resolution.
  • src/apm_cli/deps/lockfile.py: lockfile models, migration views, semantic comparison, and atomic persistence.
  • src/apm_cli/deps/installed_package.py: typed handoff from installation to lockfile assembly.

Resolution separates package identity from selected ref. Host-qualified identity is used for dependency deduplication, while deployment paths retain compatibility with the existing apm_modules layout. The resolver loads one breadth-first level in parallel but performs graph mutation in deterministic submission order.

The lockfile records exact commits or versions, source metadata, content hashes, dependency depth, parentage, deployed files, per-file hashes, MCP/LSP state, target ownership, and deployment-ledger records. It is both the reproducibility contract and the provenance input to cleanup, audit, bundle, and SBOM export.

The domain consumes AuthResolver, cache services, marketplace or registry resolution, and policy results. It returns a graph and installed-package records to the install pipeline.

Diagram reference: 2. Dependency resolution and lockfile.

Install and transaction lifecycle

src/apm_cli/install/ is the application engine behind apm install. It turns manifest and CLI intent into resolved packages, target materializations, configuration updates, cleanup actions, and lockfile state.

Important components:

  • src/apm_cli/install/request.py: immutable InstallRequest.
  • src/apm_cli/install/service.py: application service and lifecycle-hook boundary.
  • src/apm_cli/install/context.py: mutable phase context carrying graph, targets, diagnostics, policy, provenance, and counters.
  • src/apm_cli/install/pipeline.py: canonical phase ordering and commit/rollback wrapper.
  • src/apm_cli/install/phases/resolve.py: manifest, lockfile, resolver, cache, and intended-dependency setup.
  • src/apm_cli/install/phases/policy_gate.py: resolved dependency and MCP policy enforcement.
  • src/apm_cli/install/phases/targets.py: explicit, manifest, configured, detected, and fallback target selection.
  • src/apm_cli/install/phases/download.py: parallel pre-download.
  • src/apm_cli/install/sources.py: local, cached, and downloaded source strategies.
  • src/apm_cli/install/template.py: shared scan and integration template method.
  • src/apm_cli/install/phases/integrate.py: source dispatch and result aggregation.
  • src/apm_cli/install/phases/cleanup.py: manifest-driven orphan and stale-output removal.
  • src/apm_cli/install/phases/lockfile.py: lockfile and deployment-ledger assembly.
  • src/apm_cli/install/mcp/ and install/lsp/: post-package configuration reconciliation.
  • src/apm_cli/install/transaction.py: manifest snapshot and apm_modules path journal.
  • src/apm_cli/install/summary.py: completion classification and disposition-aware reporting.

The design combines an application service, a phase pipeline, source strategies, a template method, and declarative reconciliation. Reads can come from a source root while writes are directed to the deployment root, supporting drift replay and other staged operations.

The major flow is resolve -> plan -> policy -> targets -> download -> scan/integrate -> cleanup -> lockfile -> local content -> audit/finalize. MCP and LSP reconciliation are sibling configuration flows connected by command orchestration.

InstallContext is deliberately broad because it is the shared phase data bus. This makes sequencing explicit, but it also means success classification and mutation ownership must remain centralized to prevent phases and callers from interpreting the same diagnostics differently.

Diagram reference: 3. Install and transaction lifecycle.

Compilation pipeline

Compilation converts portable instruction primitives into aggregate files consumed by target harnesses. It reads local .apm/ content and already-installed dependencies; it does not resolve or download packages.

Important components:

  • src/apm_cli/commands/compile/cli.py: command validation, target selection, compiler configuration, reporting, and ownership reconciliation.
  • src/apm_cli/core/target_catalog.py: target capabilities and compile-family metadata.
  • src/apm_cli/core/target_detection.py: aliases, detection, target field parsing, and family projection.
  • src/apm_cli/compilation/agents_compiler.py: primitive discovery and output-family dispatch.
  • src/apm_cli/compilation/distributed_compiler.py: directory analysis, placement planning, rendering, and orphan detection.
  • src/apm_cli/compilation/context_optimizer.py: applyTo scoring and inherited-context minimization.
  • src/apm_cli/compilation/link_resolver.py: context and package-asset link translation.
  • src/apm_cli/compilation/claude_formatter.py: CLAUDE.md translation.
  • src/apm_cli/compilation/gemini_formatter.py: GEMINI.md import output.
  • src/apm_cli/compilation/managed_section.py: preservation of non-APM content around managed sections.
  • src/apm_cli/compilation/output_writer.py: build-ID stabilization and atomic persistence.
  • src/apm_cli/compilation/constitution.py and injector.py: optional constitution discovery and injection.

The target precedence is CLI, manifest, filesystem detection, then fallback. Targets project into compiler families such as agents, claude, gemini, or vscode. Portable primitives remain independent of these families; the family formatter is the translation boundary.

Distributed compilation analyzes project directories, places instructions according to applicability, suppresses redundant shells, resolves links, injects optional constitution content, stabilizes build IDs, writes managed files, and identifies safe orphan cleanup candidates.

Compilation and integration are related but different. Compilation emits aggregate root or distributed context. Integration materializes individual primitive files and native configuration. Installation currently stages compile-family content and may instruct the user to run explicit compilation rather than universally invoking the compile command.

Diagram reference: 4. Compilation pipeline.

Integration and file materialization

Integration is the filesystem and native-configuration boundary. It receives resolved target profiles and portable primitives, selects the appropriate integrator, renders native formats, handles adoption or collision, and returns provenance-rich materialization results.

Important components:

  • src/apm_cli/integration/targets.py: TargetProfile, PrimitiveMapping, paths, formats, scopes, capabilities, and detection.
  • src/apm_cli/integration/base_integrator.py: common collision, ownership, path validation, link resolution, synchronization, and result behavior.
  • src/apm_cli/integration/dispatch.py: shared primitive-to-integrator registry.
  • src/apm_cli/integration/coverage.py: profile and dispatch completeness checks.
  • src/apm_cli/integration/*_integrator.py: specialized instruction, skill, prompt, agent, command, canvas, hook, MCP, and LSP materializers.
  • src/apm_cli/integration/hook_integrator.py: hook parsing, event mapping, script rewriting, merging, and provenance.
  • src/apm_cli/integration/hook_native_formats.py: native hook-schema conversion.
  • src/apm_cli/integration/cleanup.py: hash-aware stale and orphan cleanup.
  • src/apm_cli/integration/_shared.py: shared MCP/LSP dependency and lockfile lookup.
  • src/apm_cli/integration/skill_transformer.py: target-specific skill metadata transformation.

The central patterns are data-driven routing and a base-class template method. Target profiles declare capabilities, dispatch selects specialized behavior, and BaseIntegrator owns common safety and provenance rules.

IntegrationResult and materialization records carry counts, locators, paths, content hashes, owners, validation status, and adoption state. Install writes these into lockfile and ledger views. Cleanup and uninstall consume the same ownership information and preserve files whose current hash indicates user modification.

Native target translation belongs here. Portable package fields should not encode one harness's schema, event names, locators, or configuration keys.

Diagram reference: 5. Integration and file materialization.

Authentication and credential resolution

Remote authentication is centralized in src/apm_cli/core/auth.py, while src/apm_cli/security/ primarily owns content scanning, executable approval, audit formats, and external scanner ingestion.

Authentication components:

  • HostInfo: immutable host kind, API base, port, and public-repository capability.
  • AuthContext: resolved token source, scheme, host information, and Git environment.
  • AuthResolver: process-scoped, thread-safe classification, credential resolution, fallback, diagnostics, and caching.
  • src/apm_cli/core/token_manager.py: environment, supported CLI, and Git credential-helper acquisition.
  • src/apm_cli/deps/host_backends.py: host-specific clone and API URL strategies.
  • src/apm_cli/deps/git_auth_env.py: non-interactive Git environment construction.

Credential precedence is host-specific. GitHub-family hosts use organization-specific or global environment variables, supported CLI credentials, and credential helpers. ADO supports PAT followed by Azure CLI bearer fallback. GitLab supports environment credentials and credential helpers. Generic hosts use credential helpers.

The resolver accepts a DependencyReference and returns an AuthContext consumed by validation, downloads, clone operations, raw-file access, marketplaces, and ref resolution. Repository path and port are retained for credential-helper disambiguation.

Security components include:

  • SecurityGate and ContentScanner for hidden-character scanning.
  • Executable approval models with deny-wins behavior.
  • Lockfile-driven file scanning and JSON, SARIF, or Markdown reports.
  • External scanner protocols and SARIF ingestion.

This separation is conceptually sound: credential resolution, content trust, and executable approval are distinct responsibilities, even though they meet in the install pipeline.

Diagram reference: 6. Authentication and credential resolution.

MCP trust, registry, and marketplace

The marketplace domain provides curated plugin discovery. A registered catalog resolves plugin@marketplace into a normal dependency reference plus provenance. The MCP registry domain provides MCP server search and metadata. Installation remains responsible for trust, policy, target configuration, and lockfile adoption.

Important marketplace components:

  • src/apm_cli/marketplace/models.py: immutable source, plugin, and manifest models.
  • src/apm_cli/marketplace/registry.py: persisted marketplace registrations.
  • src/apm_cli/marketplace/client.py: local, hosted, GitHub-family, GitLab, ADO, and generic Git fetching and caching.
  • src/apm_cli/marketplace/resolver.py: marketplace reference parsing and dependency handoff.
  • src/apm_cli/marketplace/builder.py: authoring and marketplace artifact generation.
  • src/apm_cli/marketplace/output_profiles.py: target artifact capabilities.
  • src/apm_cli/marketplace/output_mappers.py: explicit native marketplace translation.
  • src/apm_cli/marketplace/audit.py: marketplace pinning and bypass analysis.
  • src/apm_cli/marketplace/version_resolver.py: tag and version selection.

Important registry components:

  • src/apm_cli/registry/client.py: bounded, cached MCP Registry v0.1 client.
  • src/apm_cli/registry/integration.py: compatibility translation to package-shaped records.
  • src/apm_cli/registry/operations.py: existence checks and runtime/environment collection.
  • src/apm_cli/install/mcp/integration.py: current-state merge, transitive trust, policy, target writes, stale removal, and lockfile updates.

Direct MCP declarations are trusted as explicit user intent. Self-declared transitive MCP servers require root re-declaration or an explicit trust option. The current desired set is rebuilt from the root manifest and lockfile-bounded package manifests rather than accepting lockfile-only entries as authority.

Marketplace provenance records the discovery source, plugin, source URL, digest, ref, and concrete dependency. MCP lockfile state records target ownership, resolved configuration, and package provenance.

Harness-specific marketplace artifacts and MCP configuration belong in output mappers and client adapters, not in portable manifest semantics.

Diagram reference: 7. MCP trust, registry, and marketplace.

Primitives, core domain, and packaging

The core model converts author-facing YAML and files into validated in-memory contracts shared by resolution, installation, compilation, integration, and packaging.

Important components:

  • src/apm_cli/models/apm_package.py: APMPackage, manifest loading, dependencies, registries, scripts, targets, includes, and executable approvals.
  • src/apm_cli/core/apm_yml.py: canonical target and targets parsing.
  • src/apm_cli/models/dependency/: APM, MCP, LSP, remote, and resolved dependency models.
  • src/apm_cli/models/validation.py: package classification and ValidationResult.
  • src/apm_cli/models/format_detection.py: independent format evidence and normalization planning.
  • src/apm_cli/primitives/models.py: instructions, skills, prompts, agents, context, collections, and conflicts.
  • src/apm_cli/primitives/parser.py: frontmatter-to-model conversion.
  • src/apm_cli/primitives/discovery.py: local and dependency discovery with deterministic precedence.
  • src/apm_cli/core/build_orchestrator.py: bundle and marketplace producer selection.
  • src/apm_cli/core/plugin_manifest.py: native plugin manifest translation.
  • src/apm_cli/bundle/packer.py: lockfile-attested APM bundle construction.
  • src/apm_cli/bundle/plugin_exporter.py: native plugin layout generation.
  • src/apm_cli/bundle/lockfile_enrichment.py: embedded provenance and target filtering.
  • src/apm_cli/bundle/local_bundle.py: archive detection and integrity verification.
  • src/apm_cli/bundle/unpacker.py: safe additive extraction of lockfile-listed files.

Dataclasses are the primary contract style. Parsing, format detection, validation, and filesystem materialization are separate stages. Primitive discovery uses local-first precedence, followed by dependency order, while retaining conflict information.

The lockfile is the boundary between install and packaging. Bundles copy only recorded files, verify hashes, enrich embedded provenance, and optionally translate portable primitives into a native plugin layout.

The public v0.1 manifest schema and current v0.3 working-draft implementation are separate contracts. The code currently lacks explicit manifest-version negotiation, making careful schema ownership important.

Diagram reference: 8. Primitives, core domain, and packaging.

Policy, governance, drift, and audit

Policy controls what may be installed. It is not a runtime permission system; execution permissions remain with the consuming harness.

Important components:

  • src/apm_cli/policy/schema.py: immutable policy dataclasses and tri-state list semantics.
  • src/apm_cli/policy/parser.py: YAML validation and model construction.
  • src/apm_cli/policy/discovery.py: local, URL, repository, cache, pin, and inheritance discovery.
  • src/apm_cli/policy/inheritance.py: root-to-leaf tighten-only merging.
  • src/apm_cli/policy/matcher.py: canonical reference matching and deny-over-allow decisions.
  • src/apm_cli/policy/policy_checks.py: dependency, MCP, registry, target, pinning, and manifest checks.
  • src/apm_cli/policy/ci_checks.py: lockfile, ownership, configuration, and integrity checks.
  • src/apm_cli/policy/install_preflight.py: enforcement for non-pipeline and dry-run paths.
  • src/apm_cli/policy/outcome_routing.py: canonical fetch-outcome handling.
  • src/apm_cli/policy/project_config.py: fetch-failure defaults and policy hash pins.
  • src/apm_cli/drift.py: manifest, lock, source, orphan, stale-file, and MCP drift.
  • src/apm_cli/install/drift.py: cache-only replay into scratch and workspace comparison.
  • src/apm_cli/core/deployment_state.py: deployment ledger records.
  • src/apm_cli/core/deployment_ledger.py: lockfile compatibility projection.
  • src/apm_cli/update_policy.py: separate self-update distribution policy.

Policy values distinguish no opinion, explicit empty, and populated constraints. Inheritance generally intersects allowlists, unions restrictions, escalates enforcement, and applies deny-wins behavior.

Install performs resolved dependency checks before deployment and target checks after target selection. Audit performs baseline lockfile and ownership checks, optional policy evaluation, cache-only replay, and comparison against the working tree.

The deployment ledger maps locators to owners, active owner, target, runtime, scope, and hash. It is the canonical provenance model projected into compatibility lockfile fields.

Diagram reference: 9. Policy, governance, drift, and audit.

Runtime execution, adapters, cache, and export

APM separates deployment from execution. apm run executes named scripts from apm.yml, compiling referenced prompt files before invocation. Runtime adapters provide a second programmatic prompt-execution path.

Important components:

  • src/apm_cli/commands/run.py: Click entry for named scripts and parameters.
  • src/apm_cli/core/script_runner.py: script discovery, prompt compilation, runtime command recognition, and subprocess execution.
  • src/apm_cli/runtime/base.py: runtime adapter interface and streaming helper.
  • src/apm_cli/runtime/factory.py: runtime construction and preference.
  • src/apm_cli/runtime/manager.py: managed runtime installation and removal.
  • src/apm_cli/runtime/utils.py: managed-binary and PATH resolution.
  • src/apm_cli/workflow/parser.py: prompt frontmatter to WorkflowDefinition.
  • src/apm_cli/workflow/discovery.py: workflow discovery.
  • src/apm_cli/workflow/runner.py: adapter-based workflow execution.
  • src/apm_cli/adapters/client/base.py: normalized MCP client contract and native configuration boundary.
  • src/apm_cli/factory.py: client-adapter registration.
  • src/apm_cli/cache/git_cache.py: content-addressed bare repositories and immutable checkouts.
  • src/apm_cli/cache/http_cache.py: TTL, ETag, hash, and LRU HTTP caching.
  • src/apm_cli/cache/integrity.py: cache validation.
  • src/apm_cli/cache/locking.py: per-shard locks and atomic landing.
  • src/apm_cli/export/sbom.py: deterministic CycloneDX and SPDX generation.
  • src/apm_cli/export/purl.py: credential-free package identities.
  • src/apm_cli/bootstrap_mirror.py: enterprise mirror routing.
  • src/apm_cli/config.py: user-private configuration and process caching.

Recognized runtime commands are executed with argument arrays and compiled prompt content. Arbitrary authored scripts use the platform shell. Client adapters translate normalized MCP declarations into native JSON or TOML formats.

Git caching is content-addressed by normalized repository and resolved SHA. HTTP caching combines freshness, conditional requests, body hashes, and bounded eviction. SBOM export is intentionally network-free and derives only from lockfile state.

A second workflow execution path exists through workflow/runner.py, but apm run primarily uses ScriptRunner. This parallel surface contributes to runtime capability drift.

Diagram reference: 10. Runtime, adapters, cache, and export.

Cross-cutting architecture

Logging and diagnostics

CommandLogger is the semantic output owner. DiagnosticCollector supports deferred, categorized summaries. Python logging remains a separate debug channel. Commands producing machine-readable output must establish stdout/stderr policy before root-level notifications or progress output.

Authentication

AuthResolver is the shared credential authority. It classifies hosts, resolves credentials once, caches AuthContext, and applies controlled fallback. Downloaders and host backends should consume this contract rather than inspect environment variables independently.

Error handling

The code uses both exceptions and accumulated diagnostics. Exceptions express immediate inability to continue; diagnostics support phase aggregation and user summaries. Success classification must occur before lifecycle hooks, commit, and programmatic return. Otherwise the CLI and service callers can disagree about the same operation.

Caching

Git and HTTP caches are optimization layers, not authorities. Cache hits are validated through resolved SHA or body hash. Lockfile pins remain the reproducibility authority. Drift replay intentionally uses cache-only operation to avoid network-dependent audit outcomes.

Provenance and ownership

Materializers return locators, hashes, owners, and validation state. The deployment ledger is the canonical ownership model; lockfile compatibility fields project that state for existing consumers. Cleanup is hash-aware and preserves user-modified content rather than deleting solely by path.

Vendor-neutrality posture

The portable core is based on primitives, dependency references, target capabilities, and normalized MCP/LSP models. Harness-specific paths and schemas appropriately belong in target profiles, integrators, formatters, client adapters, and plugin exporters.

Neutrality weakens where generic install, auth, runtime, or hook layers contain closed vendor lists, native locator rules, or one harness's intermediate representation. New harness support should extend capability or adapter registries rather than add portable manifest fields or branches throughout orchestration code.

Surfaced architectural findings

New findings

Title Domain Severity Evidence Root-cause recommendation
Conflicting refs are discarded before conflict analysis Dependencies high deps/apm_resolver.py:608-626,792-827 Preserve every dependency edge and ref constraint through graph construction. Resolve and deduplicate in a dedicated selection phase with end-to-end conflict tests.
Transitive local dependency identity omits the declaring parent Dependencies high models/dependency/reference.py:301-319; install/phases/resolve.py:859-870 Key local dependencies by declaring-parent identity plus anchored absolute path, and derive separate installation locations.
Lockfile reader accepts unknown versions and malformed shapes Dependencies high deps/lockfile.py:641-647,692-762; docs/.../lockfile-spec.md:308-321 Validate supported versions and container shapes before construction. Raise a dedicated unsupported-version error and prevent automatic downgrade.
Install success classification is split between service and CLI Install high install/phases/lockfile.py:172-173,461-465; install/phases/finalize.py:155-161; install/service.py:107-110; install/summary.py:30-49 Classify diagnostics in the service or pipeline before post-install hooks, commit, and return. Keep the CLI presentation-only.
Compiled-output scan and write contract is not a common chokepoint Compilation high compilation/agents_compiler.py:679-688,964-1000,1418-1433; compilation/output_writer.py:1-18; docs/.../cli/compile.md:57-59 Build all output first, scan it with one blocking policy before any mutation, then write every path through CompiledOutputWriter.
Inherited require_explicit_includes is dropped Policy high policy/schema.py:99-105; policy/inheritance.py:245-261 OR-merge the field so a child cannot relax an ancestor requirement. Add parent-true and child-true inheritance tests.
Explicit audit policy bypasses inheritance-aware discovery Policy high commands/audit.py:538-554; policy/discovery.py:246-256 Route explicit and automatic policy sources through one chain-aware discovery entry point.
Incomplete policy chains remain enforceable as partial policy Policy high policy/discovery.py:447-449,501-560 Model incomplete inheritance as a distinct fetch outcome and route it through fail-closed policy instead of enforcing a potentially weaker subset.
Configured MCP registry URL is displayed but not used Registry high commands/mcp.py:18-46; registry/integration.py:11-19 Resolve URL precedence before constructing RegistryIntegration, and reuse the install registry wiring.
Marketplace registry routing is parsed but ignored Marketplace high marketplace/models.py:305-313,413-455; marketplace/resolver.py:788-820 Route registry-backed plugins through the package-registry resolver and fail closed when registry or version intent cannot be honored.
Canonical plural targets is ignored by APM bundle packing Core and bundle high models/apm_package.py:476-512; bundle/packer.py:88-155; core/apm_yml.py:41-102 Store one validated canonical target list and make compilation, installation, and packing consume it.
Invalid Copilot hook payload is written before failure is recorded Integration high integration/hook_integrator.py:1188-1233 Validate before mutation and return a failed materialization without writing. Transaction rollback should remain defense in depth.
Update notification can corrupt JSON or SBOM stdout CLI high cli.py:146-152; commands/_helpers.py:464-477; callback-local output routing in commands/pack.py, deps/why.py, and lock.py Establish output mode at the root before update checks and route or suppress notifications for machine formats.
Secret-redaction filter is attached at the wrong logging boundary CLI and auth high cli.py:99-106; descendant loggers such as core/auth.py and integration/mcp_integrator.py Attach redaction to configured handlers or a process-wide record factory, then test a descendant logger record.
Authenticated Git environment is reused for unauthenticated retries Auth medium core/auth.py:633-637,675-679,997-1028 Build a credential-free environment for unauthenticated attempts and remove inherited auth variables explicitly.
Host capability model is closed over named vendors Auth and dependencies medium models/dependency/reference.py:919-938; core/auth.py:287-299; deps/host_backends.py:494-522 Introduce an extensible host-provider registry with neutral repository coordinates, credential strategies, and API capabilities.
Vendor-specific locator logic leaks into install orchestration Install medium install/deployed_paths.py:21-38; install/manifest_reconcile.py:38-62; install/services.py:284-314 Move locator encoding and feature gates into target profiles or target adapters.
Hook intermediate representation is Copilot-shaped Integration medium integration/hook_native_formats.py:1-65,111-121 Define a vendor-neutral hook IR with explicit event, command, platform, timeout unit, matcher, and provenance fields.
Runtime capability authority is duplicated Runtime and CLI medium runtime/factory.py:14-19,91-105; runtime/manager.py:29-50; commands/runtime.py:25-27; core/script_runner.py; workflow/runner.py Create one runtime descriptor registry containing adapters, binaries, installers, capabilities, and preference.
Runtime timeout begins after blocking output consumption Runtime medium runtime/base.py:21-44; runtime/codex_runtime.py:41-76 Enforce a wall-clock deadline while streaming, terminate and reap on expiry, and test a subprocess that keeps stdout open.
Marketplace registration updates can lose concurrent writes Marketplace medium marketplace/registry.py:45-78,104-124 Protect the complete load-modify-save transaction with process and file locking.
Public v0.1 registry schema and active loader disagree Core model medium docs/public/specs/schemas/manifest-v0.1.schema.json:35-51; models/apm_package.py:101-137 Add explicit manifest-version negotiation or update implementation and normative schema together without reusing the v0.1 identity.
Install and compile lifecycle documentation contradicts implementation Compilation and docs medium docs/.../concepts/lifecycle.md:77-79; install/services.py:898-904; install/phases/finalize.py:146-153 Decide whether install owns aggregate compilation. Then align code and documentation around that single lifecycle.
Some compile outputs bypass the atomic writer Compilation low compilation/output_writer.py:1-18; agents_compiler.py:1430-1433; user_root_context.py:267-292 Route every compiled output through CompiledOutputWriter and remove duplicate build-ID finalization.

Known / in remediation

Title Domain Severity Evidence Root-cause recommendation
Compile capability authority rejects valid compile targets Compilation high core/target_catalog.py:127-132,183-200,214-219 Complete the planned single-source catalog correction so cursor, agent-skills, hermes, and intellij are compile-accepted without parallel allowlists.
Install rollback, bootstrapped manifest lifetime, and logging ownership are split Install high commands/install.py:1426-1445,1526-1532; install/transaction.py:35-78,136-171 Complete the active remediation so transaction outcome is canonical, bootstrapped apm.yml is removed only on genuine failure, and logging follows the owning layer.

Consolidated issues (auto-close on merge)

This cure folds and re-homes all 13 point fixes under their canonical owners; the superseded point PRs are closed. Merging this PR resolves:

Closes #2126
Closes #2127
Closes #2128
Closes #2129
Closes #2130
Closes #2136
Closes #2137
Closes #2138
Closes #2139
Closes #2140
Closes #2148
Closes #2149
Closes #2150
Closes #2156
Closes #2157
Closes #2158
Closes #2159
Closes #2160
Closes #2161

Architectural hardening (root-cause clusters AC1-AC7)

The 24 follow-up findings shared one root cause: a fact or mutation had more than one authority. This hardening pass completes the canonical-owner pattern and locks each cluster with both behavioral and structural guardrails.

Cluster Canonical owner / invariant Integration guard Static guard
AC1 Canonical target list, host-provider registry, runtime descriptor registry, and target-owned locator adapters tests/integration/test_architecture_authorities.py scripts/lint-architecture-boundaries.sh (AC1)
AC2 Build all outputs, scan once, write only through CompiledOutputWriter; validate hooks and lockfiles before mutation tests/integration/test_architecture_mutation_guards.py scripts/lint-architecture-boundaries.sh (AC2)
AC3 install/outcome.py owns disposition and exit semantics; policy discovery is chain-aware and incomplete chains fail closed tests/integration/test_architecture_outcome_guards.py scripts/lint-architecture-boundaries.sh (AC3)
AC4 Dependency constraints survive to selection, local identity uses anchored paths with parent provenance, and registry intent is honored tests/integration/test_architecture_intent_guards.py scripts/lint-architecture-boundaries.sh (AC4)
AC5 Root output mode owns stdout/stderr, handlers own redaction, and unauthenticated Git retries use credential-free environments tests/integration/test_architecture_io_guards.py scripts/lint-architecture-boundaries.sh (AC5)
AC6 Vendor-neutral hook IR, explicit manifest $schema negotiation, and one install/compile lifecycle contract tests/integration/test_architecture_contract_guards.py scripts/lint-architecture-boundaries.sh (AC6)
AC7 Streaming wall-clock deadlines terminate and reap runtimes; marketplace load-modify-save uses thread and file locking tests/integration/test_architecture_concurrency_guards.py scripts/lint-architecture-boundaries.sh (AC7)

The static guard is wired into the Lint job in .github/workflows/ci.yml. Legitimate exceptions require an inline # architecture-authority-exempt: <reason> annotation.

Scenario Evidence

User promise Principle Evidence
Adding a target, host, or runtime cannot leave consumers on divergent capability lists Multi-harness support tests/integration/test_architecture_authorities.py
Invalid compiled output, hook payloads, and lockfiles fail before mutation Secure by default tests/integration/test_architecture_mutation_guards.py
Service disposition, CLI exit, lifecycle hooks, and policy-chain enforcement agree Governed by policy tests/integration/test_architecture_outcome_guards.py
Conflicting refs, parent-scoped locals, and registry routes preserve declared intent Portability by manifest tests/integration/test_architecture_intent_guards.py
JSON/SBOM stdout stays parseable and unauthenticated retries carry no credentials DevX / Secure by default tests/integration/test_architecture_io_guards.py
Portable hook intent stays harness-neutral and manifest contracts are version-negotiated Vendor-neutral tests/integration/test_architecture_contract_guards.py
Runtime deadlines and concurrent marketplace writes are deterministic DevX tests/integration/test_architecture_concurrency_guards.py

Hardening validation

  • Integration: 10187 passed, 255 skipped, 2 xfailed (includes the 5 adjacent-bug regression guards; re-run green on the merged HEAD)
  • Unit/red-team: 18631 passed, 2 skipped, 21 xfailed, 88 subtests passed
  • Lint: ruff check, ruff format, pylint R0801, auth-signals, architecture boundaries, YAML I/O, file length, and portable-path guards are clean.
  • Advisory review: the APM review panel's in-scope auth, architecture, DevX, logging, supply-chain, performance, docs, and coverage findings were folded. A fully end-to-end marketplace-to-package-registry install/lock fixture remains a non-blocking follow-up.

Adjacent community bugs root-fixed on the same foundation

These open community-reported [BUG]s shared the same split-authority root as the
campaign findings, so each is fixed by extending the relevant canonical owner
(AC1/AC3/AC6) and locked by a new guard test. Where a narrower community PR already
existed, the centralized fix supersedes it (#2116 -> #2117, #2062 -> #2097, #2071 -> #2095).

Closes #2147
Closes #2103
Closes #2116
Closes #2062
Closes #2071

danielmeppiel and others added 30 commits July 10, 2026 20:16
Return exit code 1 when every positional package fails validation, matching manifest installs and the documented exit contract.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Ensure generated Copilot hook JSON defaults the required top-level version to 1 and cover it with a regression test.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Mark the validation summary as rendered before exiting so a clean total-validation failure does not append a misleading interruption warning. Addresses the CLI logging panel follow-up.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Make the existing integration test require exit code 1 so it traps the positional total-failure regression instead of passing on error text alone. Addresses the test coverage panel follow-up.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Record the corrected positional total-failure exit status under Unreleased so CI users can identify the reliability fix. Addresses the OSS growth panel follow-up.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve the Unreleased changelog overlap by retaining both reliability fixes before running the merge-commit CI mirror.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Protect the non-overwrite half of the schema-version fix with a regression test, addressing the review panel's test-coverage follow-up.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Assert that validation ran without pinning the implementation to exactly one probe, preserving the user-visible exit and message contract. Addresses Copilot inline comment 3561124008.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
GitHub did not register pull_request workflow runs for the previous synchronize event, so retrigger the CI webhook without changing the reviewed tree.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Assert the required Copilot hook schema version at the real install-service dispatch tier, addressing the final panel coverage follow-up.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Retain both concurrent Unreleased reliability entries while restoring mergeability and CI merge-commit parity.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Correct the zero-primitives progress message, type the pytest fixture, and lock the validate boundary with a mutation-proven regression test. Addresses panel and Copilot follow-ups.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Centralize managed deployment-root derivation, keep absolute path validation on the shared containment guard, add direct serialization coverage, and record the fix in the changelog. Addresses panel follow-ups from PR #2135.

apm-spec-waiver: harness-install reliability fix for Claude CLAUDE_CONFIG_DIR outside HOME; no OpenAPM artifact or wire behavior change

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Reuse the broadened empty-output signal for formatter suppression and document the validation/watch caller boundary. Addresses the final Python architecture panel follow-up.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Qualify path containment guidance for global installs using configured target roots. Addresses the final supply-chain panel finding for PR #2135.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Suppress the contradictory zero-output warning for expected orphan cleanup, preserve hand-authored files without irrelevant duplicate-context advice, and add mutation-proven message regressions. Addresses the terminal logging and architecture panel findings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Derive compile and install target help from the accepted target catalog, and use the same catalog for unknown-target guidance.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ellij

The kiro discoverability test hard-coded the brittle 'all' target join
(copilot+...+kiro), which the accepted-target catalog now supersedes as
the single source of the help Values list. Assert each advertised target
-- including the MCP-only intellij target this PR adds -- is discoverable
in both install and compile help instead.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The stricter APMPackage.from_apm_yml identity validation (this PR) is the
correct authority for audit/policy surfaces, but it leaked into the deps
list/info display helpers: a manifest that merely empties 'version' now
raised, collapsing the graceful '@unknown' render into an alarming
'@error' that masks the package. Add a shared _tolerant_identity fallback
so the display surface stays lenient (empty/missing version -> unknown)
while genuinely unparsable YAML still reports error. Make deps info
symmetric with deps list and cover both with regressions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
apm-spec-waiver: Transactional resolution staging enforces existing install atomicity expectations; no new OpenAPM artifact or wire behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
apm-spec-waiver: Deployment reconciliation gives update/compile the parity install already has; enforces existing lockfile ownership semantics, no new OpenAPM wire behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
danielmeppiel and others added 8 commits July 11, 2026 18:58
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: ship_with_followups

PR #2155 is ready to ship: it hardens APM's architecture, security boundaries, machine output, and lifecycle behavior with comprehensive regression coverage.

cc @sergio-sisternes-epam -- a fresh advisory pass is ready for your review.

The panel's first pass surfaced concrete compatibility, credential-isolation, identity, cancellation, performance, coverage, and documentation issues. The author folded every in-scope item: host hints can no longer redirect credentials across recognized providers; Git authorization channels and exception traces are scrubbed; registry identities come from declared coordinates; lockfile and hook payloads validate before mutation; local DAG identity is anchor-based; non-success installs stop before MCP/LSP and post-install hooks; runtime buffering is bounded; and machine-output aliases reserve stdout.

Validation now reports 10,184 integration tests and 18,631 unit tests passing, with ruff, formatting, pylint duplication, auth signals, architecture boundaries, YAML I/O, portable paths, and file-length checks clean. Documentation and the changelog describe the resulting user guarantees. The maintainer retains the merge decision.

Aligned with: portability by manifest through strict, round-tripped lock state; secure by default through fail-closed identity and credential boundaries; governed by policy through complete-chain enforcement; multi-harness and multi-host support through canonical registries; pragmatic package-manager UX through deterministic cancellation, failures, and machine output.

Growth signal. The release story is user trust: deterministic installs and clean automation across registries, hosts, policies, hooks, and failure paths.

Panel summary

Persona B R N Takeaway
Python architect 1 2 0 Contract, output-mode, and IR findings were folded.
CLI logging expert 1 2 0 Traceback redaction, output aliases, and failure wording were folded.
DevX UX expert 3 2 0 Compatibility, cancellation, registry identity, and recovery prose were folded.
Supply-chain security expert 4 0 0 Registry, auth, lockfile, and hook fail-closed gaps were folded.
OSS growth hacker 0 2 0 Lifecycle and release prose now lead with user outcomes.
Auth expert 2 1 0 Provider conflicts and inherited Git authorization channels were fixed.
Doc writer 0 4 0 Verified lifecycle, policy, registry, and contract drift was corrected.
Test coverage expert 3 2 0 CLI exit, post-hook, lockfile roundtrip, and scenario evidence were added.
Performance expert 1 1 0 Local DAG amplification and unbounded runtime buffering were fixed.

B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength from the initial pass, not gates. The findings were folded before this update.

Top 1 follow-up

  1. [Test coverage expert] Add a full marketplace-to-package-registry install and lock fixture -- this would defend the complete cross-layer identity flow beyond the current registry DependencyReference integration guard.

Recommendation

Ship the current commit. Track the marketplace-to-package-registry end-to-end fixture as non-gating defense-in-depth coverage.


Full per-persona findings from the initial pass

Python architect

  • [blocking] OpenAPM v0.1 rejected its documented default registry selector. Folded with v0.1 registries.default negotiation and integration coverage.
  • [recommended] Machine-output authority missed documented JSON and SARIF aliases. Folded with command-aware aliases and tests.
  • [recommended] Frozen hook IR retained mutable dictionaries. Folded with recursive immutable snapshots and edge-only rendering.

CLI logging expert

  • [blocking] Exception tracebacks bypassed handler redaction. Folded by redacting formatted exception text.
  • [recommended] Option-based machine formats could receive startup notices on stdout. Folded in root output-mode rules.
  • [recommended] Handled install failures ended as interruptions. Folded with disposition-aware failure completion.

DevX UX expert

  • [blocking] Legacy null lockfile mappings failed strict validation. Folded with null normalization.
  • [blocking] Registry-routed marketplace plugins used display names as package identity. Folded with declared owner/repo identity.
  • [blocking] Cancelled installs continued into MCP/LSP work. Folded with terminal-disposition return and CLI coverage.
  • [recommended] Update-notification spacing could contaminate machine stdout. Folded with stderr-aware spacing.
  • [recommended] Release notes lacked user recovery outcomes. Folded into CHANGELOG.md and docs.

Supply-chain security expert

  • [blocking] Marketplace identity could diverge from declared source. Folded with validated owner/repo coordinates.
  • [blocking] GIT_CONFIG_PARAMETERS survived unauthenticated retry cleanup. Folded and tested.
  • [blocking] Lockfile deployment rows were not structurally validated. Folded while preserving legacy hashless rows.
  • [blocking] Hook event payload values could bypass validate-before-mutate. Folded with event/entry validation.

OSS growth hacker

  • [recommended] Producer compile guidance contradicted explicit compilation. Corrected.
  • [recommended] Changelog prose led with internals instead of user trust outcomes. Corrected.

Auth expert

  • [blocking] type: gitlab could override recognized GitHub/GHE/ADO hosts. Folded with conflict rejection tests.
  • [blocking] GIT_CONFIG_PARAMETERS preserved an authorization channel. Folded.
  • [recommended] Scrubbing removed unrelated indexed Git config. Folded by compacting and retaining non-credential settings.

Doc writer

  • [recommended] Producer compile behavior drifted. Corrected.
  • [recommended] Policy docs described partial-chain enforcement. Corrected to fail closed.
  • [recommended] Manifest docs omitted marketplace registry routing. Corrected.
  • [recommended] Marketplace docs omitted the registries experimental prerequisite. Corrected.

Test coverage expert

  • [blocking] Parent/anchor lockfile fields lacked roundtrip coverage. Added.
  • [blocking] Diagnostic disposition lacked a real CLI exit assertion. Added.
  • [blocking] Failed install post-hook suppression lacked integration coverage. Added.
  • [recommended] Marketplace registry routing lacks a full install-to-lock fixture. Deferred as the one follow-up above.
  • [recommended] PR body lacked scenario evidence. Added in the architectural hardening section.

Performance expert

  • [blocking] Declaring-parent identity amplified shared local DAGs. Folded by deduplicating on anchored physical path while retaining parent provenance.
  • [recommended] Runtime output buffering was unbounded. Folded with a bounded cancellation-aware queue and reader join.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

@danielmeppiel

danielmeppiel commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Mergeability summary (honest proof ledger)

This PR is the consolidated outcome of a three-round reliability campaign (stress-test -> confirm -> fix) plus a follow-on architectural hardening pass and an adjacent-bug root-fix sweep on the same foundation. It closes 24 issues and locks each fix behind a dual guardrail (regression test + static CI guard) so a fix in one place can no longer silently break another. Everything below is independently verified on the merged HEAD; caveats are called out explicitly.

1. Issues this PR fixes (auto-close on merge)

All 24 are registered as GitHub closingIssuesReferences against base main (verified: totalCount = 24), so merging closes them automatically.

Reliability bugs (13) - found and confirmed by the campaign:

Issue Title
#2126 apm install <positional URL> exits 0 when the install totally fails
#2127 apm audit --ci misses local-path sub-package MCP source drift (exits 0)
#2128 Generated GitHub Copilot hook JSON omits the required top-level version: 1
#2129 Global Claude install with CLAUDE_CONFIG_DIR outside HOME partial-deploys then exits 1
#2130 apm compile --clean skips orphan removal when the last primitive is removed
#2136 apm audit --ci misses local-path sub-package MCP declaration REMOVAL (exits 0)
#2137 audit --ci and policy status --check silently accept schema-invalid manifest/policy keys
#2138 compile --help and unknown-target error omit the accepted intellij target
#2139 update/compile leave stale deployed_files + artifacts when the target universe contracts
#2140 Cyclic-dependency rejection leaves an un-resumable apm_modules snapshot
#2148 Uninstalling the last-writer of a shared deployed file drops lockfile ownership
#2149 Contracting the target set strands APM-managed MCP servers in the removed harness config
#2150 Semver install/update drops the ADO bearer auth scheme (uses Basic auth)

Architectural follow-ups folded in (6) - filed during the campaign, root-fixed here:

Issue Title
#2156 Add ADO stale-PAT 401-to-bearer retry fallback in ref resolution
#2157 Define canonical hook provenance without _apm_source translation metadata
#2158 Adopt legacy lockfiles predating mcp_target_servers on upgrade
#2159 Benchmark and optimize deployment ledger mutation paths at scale
#2160 Make uninstall deployment-state persistence atomic
#2161 Route install exception-handler output through the logging owner

Adjacent community [BUG]s root-fixed on the same canonical-owner foundation (5):

These were open community-reported bugs that turned out to be the SAME split-authority root shape as the campaign findings. Rather than patch them in isolation, each is fixed by extending the relevant canonical owner (AC1/AC3/AC6) and is regression-locked by a new guard test. Where a narrower community PR already existed, the centralized fix supersedes it.

Issue Title Canonical owner extended Supersedes
#2147 apm init and apm install disagree on the accepted target vocabulary AC1 - init reuses the single install-accepted target catalog -
#2103 Declared plugin components that do not exist are silently ignored AC3 - install outcome fails closed before commit -
#2116 apm install --skill with no matching skill is a silent no-op (exits 0) AC3 - requested components must resolve or fail closed #2117
#2062 Claude flat hook entries are emitted without the required matcher/hooks nesting AC6 - neutral hook IR -> Claude integrator emits native shape #2097
#2071 Kiro hooks are emitted in a legacy pre-1.0 schema AC6 - neutral hook IR -> Kiro integrator emits current v1 schema #2095

2. Root-cause hardening (why one fix can no longer break another)

The reliability bugs shared one root shape: an authority (target vocabulary, install outcome, policy chain, file write, hook shape, I/O, concurrency) was split or incompletely applied, so a fix on one path missed a sibling path. The hardening centralizes each into a single canonical owner, protected by a regression test + a static guard in scripts/lint-architecture-boundaries.sh (wired into CI). The 5 adjacent community bugs above are the strongest evidence the foundation generalizes: each fell out by extending an existing owner, not by adding a new special case.

Cluster Centralized authority Regression guard
AC1 Canonical target / host-provider / runtime registries tests/integration/test_architecture_authorities.py
AC2 Atomic compiled writes, hook validation, strict lockfiles tests/integration/test_architecture_mutation_guards.py
AC3 Canonical install outcomes + fail-closed policy chains tests/integration/test_architecture_outcome_guards.py
AC4 Preserved refs, anchored locals, registry intent tests/integration/test_architecture_intent_guards.py
AC5 Process-wide output mode, redaction, clean auth retries tests/integration/test_architecture_io_guards.py
AC6 Neutral hook IR + manifest negotiation (vendor-neutral) tests/integration/test_architecture_contract_guards.py
AC7 Streaming deadlines + marketplace locking tests/integration/test_architecture_concurrency_guards.py

Architecture map (BEFORE -> AFTER per domain, with assessments): see the architecture diagram comment and the "Architecture analysis (onboarding guide)" section in the PR body.

3. Proof of mergeability

Proof Result How verified
Hermetic integration suite 10187 passed, 255 skipped, 2 xfailed Re-run locally on merged HEAD (db5a7b7b); see xdist note below
Unit suite green CI Build & Test Shard 1 & 2 (Linux) pass on this HEAD
Architecture guardrail tests (test_architecture_*) 44 passed (not skipped) Run explicitly on HEAD
Lint chain (ruff check, ruff format, pylint R0801=10.00, auth-signals, arch-boundaries) clean Re-run locally; CI Lint green
Static guard lint-architecture-boundaries.sh (AC1-AC7) clean (exit 0) Re-run locally; wired into CI
PR checks all required pass; deploy skipped (expected) gh pr checks 2155
Closing-issue links 24 registered vs base main closingIssuesReferences

4. Honesty and caveats (nothing hidden)

Recommendation: ship. The reliability findings and 5 adjacent community bugs are fixed at root on one canonical-owner foundation, every fix is regression-locked by a test plus a static CI guard, the vendor-neutral contract is preserved (neutral hook IR, no apm-* invented fields, no harness translation shim), and the full integration + unit + lint gates are green on the merged HEAD. The two adjacent bugs above (#2154, #2067) are the honest next lane.

danielmeppiel and others added 2 commits July 11, 2026 23:21
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The cure's dependency resolver anchored every transitive local package by
its absolute, resolved on-disk path and stored that string as the package
identity. That identity feeds three serialized lockfile fields --
dependencies[].anchored_local_path, the local: cycle/owner identity used by
declaring_parent, and the deployment-ledger owner rows -- so a regenerated
apm.lock.yaml embedded 105 absolute developer-home paths, making the
committed artifact non-portable and non-deterministic across machines and CI.

Fix the single compute site: introduce one canonical owner,
APMDependencyResolver._portable_anchor_identity, that records an in-project
package relative to the project root in forward-slash POSIX form (matching how
directly-declared local owners already serialize) and falls back to a stable
absolute POSIX identity only for out-of-project local deps. The value is
identity-only and never re-opened as a filesystem path, so relativising it is
behaviour-preserving.

Guardrails:
- Unit tests exercise the canonical helper directly (in-project, nested,
  out-of-project, unknown-base).
- A committed-artifact guard scans the real apm.lock.yaml and fails if any
  anchored_local_path, local: owner identity, or home-directory prefix ever
  regenerates as an absolute path.
- Lockfile regenerated with the fixed resolver: 0 absolute paths, audit --ci
  9/9 no drift, deterministic steady state.

Also folds the primitive-encoding of the single-canonical-owner discipline
into the python-architect / apm-primitives-architect agents, the python and
integrators instructions, the python-architecture skill, and a new
architecture.instructions primitive (with deployed copies), so the same
discipline that motivated this fix is captured for future contributors.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8e13654a-d2ea-4310-9261-3a38e47db5f0
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: needs_rework

PR #2155 is broadly portable and green, but exact-head reproductions expose credential leakage, file deletion, ref mismatch, and corrupted JSON output that warrant a narrow repair pass.

cc @sergio-sisternes-epam -- a fresh advisory pass is ready for your review.

The green CI matrix is meaningful: 18,356 local unit tests, 10,187 hermetic integrations, 18,283 native Windows unit tests, and Windows binary, smoke, PowerShell install, integration, and ADO E2E checks establish a strong cross-platform baseline. They do not exercise the exact branches reached by the panel's controlled reproductions.

The highest-signal findings converge on user-visible correctness and secure defaults: credential sanitization is bypassed in three paths, ownership transfer can delete the winning package file, and package-only download deduplication can place content from a different ref than the resolved node records. The output-mode findings describe the same machine-readable-output defect at different breadths.

Keep the response surgical: repair the reproduced credential, ownership, ref-deduplication, and output-routing defects and add focused regression tests. Do not expand this PR for unknown-target suggestions, quadratic optimization, skipped marketplace coverage, stale metrics, or prose polish. Once the focused repairs pass the existing matrix, ship immediately.

Dissent. Python Architect rated positional output-mode detection as recommended, while CLI Logging rated the broader valid-flag failure as blocking. The broader classification carries because multiple supported invocations reproducibly corrupt JSON, while the fix remains a small normalization-and-test change.

Aligned with: portable by manifest, secure by default, governed by policy, multi-harness/multi-host, and pragmatic package-manager behavior.

Panel summary

Persona B R N Takeaway
Python Architect 0 1 0 Canonical owners are coherent; normalize root-prefixed output flags.
CLI Logging Expert 1 0 0 Attached/root-prefixed output flags can corrupt JSON stdout.
DevX UX Expert 1 1 0 Ownership handoff can delete the winning deployment.
Supply Chain Security Expert 2 0 0 Two paths can reintroduce or mis-scope Git credentials.
OSS Growth Hacker 0 1 1 Ship after focused repairs; refresh stale metrics later.
Auth Expert 1 0 0 ADO bearer retry bypasses the scrubbed auth environment.
Doc Writer 0 0 1 Docs are truthful; one duplicate row is skippable.
Test Coverage Expert 0 2 0 Two critical promises lack integration-floor regression traps.
Performance Expert 1 1 0 Package-only download dedup can materialize the wrong ref.

B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.

Top 5 follow-ups

  1. [Supply Chain Security Expert] (blocking-severity) Keep AuthResolver's sanitized environment authoritative and restrict GitLab credentials to trusted host classification -- raw environment merging and manifest-controlled host typing can leak credentials.
  2. [Auth Expert] (blocking-severity) Carry the scrubbed authentication context into the ADO PAT-to-bearer retry -- rebuilding from os.environ retains inherited authorization headers.
  3. [DevX UX Expert] (blocking-severity) Make collision ownership handoff non-destructive -- loser cleanup can delete a path after ownership transfers to the winner.
  4. [Performance Expert] (blocking-severity) Deduplicate downloads by resolved ref/content identity rather than package name -- parallel conflicting refs can leave metadata and disk content inconsistent.
  5. [CLI Logging Expert] (blocking-severity) Normalize root-prefixed and attached output flags before routing update notices -- supported Click forms contaminate JSON stdout.

Recommendation

Apply only the focused fixes for credential scoping, ownership cleanup, ref-aware deduplication, and JSON output routing, with regression tests for each reproduction. After that targeted pass clears the already-green matrix, ship without taking on lower-priority polish or broader redesign.


Full per-persona findings

Python Architect

  • [recommended] Recognize policy status after root flags before reserving JSON stdout at src/apm_cli/core/output_mode.py:30.
    Exact-head apm --verbose policy status --output json writes an update notice before the JSON document.

CLI Logging Expert

  • [blocking] Recognize attached and globally-prefixed machine-output options at src/apm_cli/core/output_mode.py:21.
    --output=json, -ojson, --format=json, -fjson, and root prefixes evade detection and corrupt machine-readable stdout.

DevX UX Expert

  • [blocking] Cross-package ownership handoff can delete the winning package's deployed file at src/apm_cli/install/phases/lockfile.py:256.
    Exact-head reproduction ended with file_exists=False while the ledger assigned the path to the winner.
  • [recommended] Unknown-target recovery lists only all for several commands.

Supply Chain Security Expert

  • [blocking] Package-controlled host_type: gitlab can send the global GitLab PAT to an arbitrary host at src/apm_cli/core/host_providers.py:165.
  • [blocking] Preflight environment rebuilding restores inherited Git authorization channels at src/apm_cli/install/pipeline.py:179.

OSS Growth Hacker

  • [recommended] Refresh stale exact-head metrics in the PR body.
  • [nit] Collapse the duplicate apm compile reference row.

Auth Expert

  • [blocking] ADO bearer retries retain inherited Git Authorization headers at src/apm_cli/marketplace/ref_resolver.py:318.

Doc Writer

  • [nit] Remove the duplicate apm compile command row.

Test Coverage Expert

  • [recommended] Portable transitive lock identities lack an install-to-lockfile assertion in tests/integration/test_transitive_chain_e2e.py.
  • [recommended] Marketplace registry routing lacks a full install and lockfile fixture in tests/integration/test_marketplace_e2e.py.

Performance Expert

  • [blocking] Parallel conflicting refs can select one ref while materializing another at src/apm_cli/deps/apm_resolver.py:1155.
  • [recommended] Per-owner ledger replacement makes lockfile assembly quadratic.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6918e42-c142-41d3-9511-7647bdb80195
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: ship_with_followups

PR #2155 closes the reproduced deployment, credential-routing, ref-selection, and machine-output defects at a fully green head; two single-owner extractions and one GitLab docs correction remain bounded follow-ups.

cc @sergio-sisternes-epam -- a fresh advisory pass is ready for your review.

At exact head 86b9546b5, the evidence supports shipping: the PR is MERGEABLE, 22 checks succeed, 18,369 unit and 10,189 hermetic integration tests pass, and six mutation-break gates demonstrate closure. Performance, DevX, logging, coverage, docs, and growth reviewers found no current behavioral blocker. The repair delta is bounded to 17 files (+506/-31).

The architect is right about the target design: ownership transfer and dependency winner selection should each have one canonical owner. Today the duplicated decisions agree, are deterministic, and are mutation-tested, so they are future-drift risks rather than demonstrated correctness defects. Because this PR explicitly establishes single-owner discipline, fold them as two behavior-preserving private extractions, not a redesign. The secured GitLab trust boundary also needs a two-page docs alignment.

Dissent. Performance and DevX consider the behavioral defects closed; Python Architect flags duplicated authority as blocking-severity. CEO arbitration sides with the architect on target design and with Performance/DevX on present correctness: fold narrowly, then ship.

Panel summary

Persona B R N Takeaway
Python Architect 2 0 0 Behavior is fixed; two decision algorithms still have duplicate owners.
CLI Logging Expert 0 0 0 All attached/root-prefixed JSON forms now preserve stdout.
DevX UX Expert 0 0 0 Ownership handoff preserves the winner file.
Supply Chain Security Expert 0 1 0 Credential blockers are closed; align GitLab docs.
OSS Growth Hacker 0 0 0 No adoption-facing shipping issue.
Auth Expert 0 1 0 Auth behavior is secured; align GitLab docs.
Doc Writer 0 0 0 No material code/docs inconsistency beyond the scoped auth clarification.
Test Coverage Expert 0 0 0 All six repairs meet their tier floors.
Performance Expert 0 0 0 Ref selection/materialization is deterministic and mutation-tested.

Counts are signal strength, not gates. The maintainer ships.

Top 3 follow-ups

  1. [Python Architect] (blocking-severity) Make DeploymentReconciler the sole owner of prior-claim eligibility and ownership transfer; lockfile.py should supply facts, not recompute policy.
  2. [Python Architect] (blocking-severity) Extract one private deterministic winner selector used by both download dispatch and flattening while retaining loser conflict reporting.
  3. [Auth/Supply Chain] State that type: gitlab controls backend routing only; global GitLab tokens require gitlab.com, GITLAB_HOST, or APM_GITLAB_HOSTS.

Recommendation

Fold only the two behavior-preserving private extractions plus the GitLab documentation correction, add narrow architecture guards, rerun the mapped focused/mutation gates and the full matrix, then request one final panel pass.


Full per-persona findings

Python Architect

  • [blocking] LockfileBuilder independently computes prior-claim eligibility before canonical DeploymentReconciler ownership transfer at src/apm_cli/install/phases/lockfile.py:251.
  • [blocking] Download dispatch and flatten_dependencies independently derive the same first-wins dependency selection at src/apm_cli/deps/apm_resolver.py:683.

Supply Chain Security Expert / Auth Expert

  • [recommended] Align docs/src/content/docs/getting-started/authentication.md and packages/apm-guide/.apm/skills/apm-usage/authentication.md with the new GitLab host trust boundary.

CLI Logging Expert

No findings.

DevX UX Expert

No findings.

OSS Growth Hacker

No findings.

Doc Writer

No findings.

Test Coverage Expert

No findings.

Performance Expert

No findings.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6918e42-c142-41d3-9511-7647bdb80195
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: needs_rework

Runtime, architecture, docs, and broad CI are ready, but one executable security contract at exact head 9b3319c39 still contradicts trusted-host token scoping.

cc @sergio-sisternes-epam -- a fresh advisory pass is ready for your review.

Eight specialist reviews are clean. The canonical deployment and dependency-winner owners are now centralized, prior behavioral defects remain closed, GitLab trust-boundary docs match the runtime, and 22 checks pass. One exact-head test supplied stronger contrary evidence: tests/test_github_downloader.py::TestGiteaGogsApiVersionNegotiation::test_object_form_type_gitlab_routes_bespoke_host_to_gitlab_api still requires PRIVATE-TOKEN == glpat-bespoke for untrusted code.acme.com, and fails against the secured implementation.

The broad reported suites omit this root-level test file, so repository evidence is internally inconsistent. Correct only the executable contract: the type-only untrusted host receives no global PAT; the same host explicitly trusted through APM_GITLAB_HOSTS receives it. Ensure both cases are under CI discovery, then ship.

Panel summary

Persona B R N Takeaway
Python Architect 0 0 0 Both canonical-owner findings are closed; ship.
CLI Logging Expert 0 0 0 No output regression.
DevX UX Expert 0 0 0 Winner-file survival remains intact.
Supply Chain Security Expert 1 0 0 One stale test still demands forbidden PAT forwarding.
OSS Growth Hacker 0 0 0 No adoption blocker.
Auth Expert 0 0 0 Auth blockers and docs are aligned.
Doc Writer 0 0 0 Both auth docs are concise and correct.
Test Coverage Expert 0 0 0 Discovered mapped suites are green.
Performance Expert 0 0 0 Shared winner selection remains deterministic and cheap.

Recommendation

Update the stale untrusted-host assertion, add the explicit trusted-host counterpart, and place both under CI discovery. No runtime or architectural change is requested.


Full per-persona findings

Supply Chain Security Expert

  • [blocking] tests/test_github_downloader.py:2515 requires forwarding a global GitLab PAT to a type-only untrusted host.
    Exact-head targeted run: 1 failed, 3 passed. The runtime and docs correctly require gitlab.com, GITLAB_HOST, or APM_GITLAB_HOSTS for global token trust.

All other panelists returned no findings.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

danielmeppiel and others added 2 commits July 12, 2026 02:45
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cd93cabb-ca6e-4677-94cc-6a50a68273e5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6918e42-c142-41d3-9511-7647bdb80195
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: ship_now

GitLab routing is runtime-correct, secure, and fully validated; only a bounded test-hermeticity improvement remains.

cc @sergio-sisternes-epam -- a fresh advisory pass is ready for your review.

The evidence supports shipping exact head 3e7a4158: the PR is MERGEABLE, all 22 required checks succeeded, and the focused, unit, integration, and audit suites passed. Seven panelists found no issues. Python Architect and Auth Expert independently identified the same recommended test-only concern: the new routing tests permit a real git fetch attempt before their mocked REST fallback.

That concern does not weaken the runtime or security contract. It is a future-flake risk, not a product defect. Per the bounded-scope constraint, do not expand this PR or reopen the implementation.

Aligned with: secure by default, multi-harness/multi-host, and pragmatic package-manager behavior.

Panel summary

Persona B R N Takeaway
Python Architect 0 1 0 Architecture is ready; tests could force fallback more directly.
CLI Logging Expert 0 0 0 No CLI output findings.
DevX UX Expert 0 0 0 No DevX regression.
Supply Chain Security Expert 0 0 0 Trusted/untrusted GitLab token contracts are correct.
OSS Growth Hacker 0 0 0 No adoption issue.
Auth Expert 0 1 0 Runtime auth is correct; tests could avoid real fetch attempts.
Doc Writer 0 0 0 Documentation remains aligned.
Test Coverage Expert 0 0 0 Focused, unit, integration, CI, and audit evidence are green.
Performance Expert 0 0 0 No production performance change.

Counts are signal strength, not gates. The maintainer ships.

Top follow-up

  1. [Python Architect + Auth Expert] Patch GitSparseFileTransport.fetch_file to raise a deterministic transport error in the new routing tests, preventing real fetch attempts against code.acme.com. This is test-only and non-blocking.

Recommendation

Ship exact head 3e7a4158. Track only the small test transport mock as a bounded follow-up; no runtime changes or broader refactoring are justified.


Full per-persona findings

Python Architect

  • [recommended] Isolate the GitLab REST contract tests from the primary git transport at tests/unit/deps/test_github_downloader_gitlab_routing.py:23.
    Mock GitSparseFileTransport.fetch_file to fail deterministically so the tests exercise REST routing without external-network dependence.

Auth Expert

  • [recommended] Make the GitLab routing tests hermetic at tests/unit/deps/test_github_downloader_gitlab_routing.py:26.
    Prevent real git fetches before the mocked REST fallback.

All other panelists returned no findings.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: ship_now

PR #2155 closes the auth-test hermeticity gap without changing runtime behavior.

cc @sergio-sisternes-epam -- a fresh advisory pass is ready for your review.

The panel unanimously supports shipping exact head 26425f2ecf311e8cc3dc4d527eec12e5b8af9fb1. Both transport boundaries are replaced, AuthResolver external fallback is disabled, and the latest delta changes only two test files.

Validation is decisive: 22 successful checks, 4 focused tests, 18,373 unit tests, 10,191 hermetic integration tests, and a 9/9 audit. No blocking or recommended findings remain.

Aligned with: secure by default and multi-harness/multi-host behavior.

Panel summary

Persona B R N Takeaway
Python Architect 0 0 1 Closure verified; dependency injection is correctly used.
CLI Logging Expert 0 0 0 No findings.
DevX UX Expert 0 0 0 No findings.
Supply Chain Security Expert 0 0 0 Credential-routing tests are hermetic.
OSS Growth Hacker 0 0 0 No adoption impact.
Auth Expert 0 0 0 Trusted/untrusted token contracts are deterministic.
Doc Writer 0 0 0 Documentation remains aligned.
Test Coverage Expert 0 0 0 Focused and full evidence is green.
Performance Expert 0 0 0 No production performance change.

Counts are signal strength, not gates. The maintainer ships.

Recommendation

Merge this exact head as-is; no follow-up work is warranted.


Full per-persona findings

Python Architect

  • [nit] Design pattern record only; no action required. Tests inject AuthResolver with external fallback disabled and replace both transport boundaries for deterministic REST-path coverage.

All other panelists returned no findings.

This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.

@danielmeppiel danielmeppiel merged commit 0c56ce3 into main Jul 12, 2026
23 checks passed
@danielmeppiel danielmeppiel deleted the apm-rt-arch-c1 branch July 12, 2026 05:30
danielmeppiel added a commit that referenced this pull request Jul 12, 2026
Define the evidence-backed grouping and validation contract for restoring every issue closed by PR #2155 to the v0.25.0 changelog.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239
danielmeppiel added a commit that referenced this pull request Jul 12, 2026
Plan the issue-set validation, grouped changelog rewrite, PR body synchronization, and release-gate checks for #2155.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239
danielmeppiel added a commit that referenced this pull request Jul 12, 2026
Expand PR #2155 into grouped user outcomes and link every issue it closed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239
danielmeppiel added a commit that referenced this pull request Jul 12, 2026
* chore: release v0.25.0

Bump apm-cli and the lockfile to 0.25.0, move sanitized user-facing changes into the dated changelog section, and confirm the CI lint mirror passes. Post-merge: tag v0.25.0 to trigger the release workflow.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239

* docs: design community-fix release notes

Define the evidence-backed grouping and validation contract for restoring every issue closed by PR #2155 to the v0.25.0 changelog.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239

* docs: plan community-fix release notes

Plan the issue-set validation, grouped changelog rewrite, PR body synchronization, and release-gate checks for #2155.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239

* docs: restore v0.25.0 community fixes

Expand PR #2155 into grouped user outcomes and link every issue it closed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239

* chore: remove superpowers planning artifacts

Remove the repository-local superpowers planning tree and ignore future local planning artifacts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 425fcf34-8659-4f23-a91e-a5a590208239

---------

Co-authored-by: danielmeppiel <danielmeppiel@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment