GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — fix(claude): prepare intact user plugins through native registration by danielmeppiel · Pull Request #3290 · microsoft/apm

Conversation

@danielmeppiel

@danielmeppiel Daniel Meppiel (danielmeppiel) commented Oct 20, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

fix(claude): register complete user plugins without loose projection

Description

TL;DR

Prepare eligible global Claude plugins through one native registration owner, preserving complete resources, plugin-root context, activation choices and recoverable ownership.
Reuse canonical acquisition, authorization, scanning, lockfiles and the opt-in native fingerprint; ordinary package hashing stays unchanged.
Revived 2026-11-12: merges current main a14ee1521 and shares its prepared deployment plan, preserving distinct native-format owners and read-only local-source verification. Merge gate: Native Claude check (10 minutes).
The implementation remains a draft: metadata and engineering qualification do not establish actual Claude hook execution.

Warning

Actual SessionStart, SubagentStart and UserPromptSubmit witnesses do not exist.
Native consent was not granted. Keep this PR draft and the issue open; no trust, activation, invocation, merge or closure is authorized here.

Problem (WHY)

  • The reported legacy route in [BUG] Hooks that read process.env.CLAUDE_PLUGIN_ROOT are registered but never copied, and fail silently at runtime #3191 retains process.env.CLAUDE_PLUGIN_ROOT expressions but omits indirectly referenced resources and supplies no native plugin root.
  • Generated normalization must not turn selected raw-plugin intent into authored APM content on replay.
  • Legacy package hashes omit publisher __pycache__ resources and executable modes; original same-pin mutation witnesses exposed native integrity gaps.
  • With both targets selected, an opaque Codex bundle must not be reinterpreted by the Claude registrar.
  • Registration success is not execution proof. Following Agent Skills' "Refine with real execution", this evidence names substituted boundaries and leaves missing native results explicit.

Approach (WHAT)

  • Admit complete supported plugins only after effective-target, capability and executable-approval gates; refuse symlinks and real skill subsets.
  • Use one DeployableSourcePlan and the canonical native hash, retaining target-specific registrars and ledgers.
  • Suppress loose Claude projection only for admitted Claude plugins; preserve canonical all-projection suppression for opaque Codex bundles.
  • Reconcile after saved-lock/integrity gates; preserve existing activation and create new native registrations disabled.
  • Refuse automatic transition over retained package-owned hooks; require explicit removal instead of deleting retained-target state.
  • Retain ownership intent and empty recovery locks on native cleanup failure; refuse changed same-pin and unfingerprinted legacy adoption.

Implementation (HOW)

Files Responsibility
claude_plugins/admission.py, client.py, registrar.py Claude-specific admission, pinned metadata adapter, complete fingerprint/source-pin ownership, recovery and read-only verification.
install/context.py, phases/claude_plugins.py, pipeline.py Separate native queues/phases, saved-lock handoff, lazy phase import and unchanged typed-error passthrough.
install/deployment_plan.py, services.py, target_filter.py, target_warnings.py Share one native admission between batch skill preflight and integration; preserve target-specific projection, personal loose skills and retained hooks.
install/legacy_plugin_compat.py, drift.py Preserve explicit normalized legacy intent; verify native source/cache fingerprints and normalize local audit sources only in scratch.
integration/mcp_config_view.py, claude_plugins/registrar.py Read local Claude MCP declarations from main's install-synthesized apm_modules/_local manifest (#3540), never the publisher source; compare local lock hashes with original source snapshots independently of complete native cache fingerprints.
integration/hook_integrator.py, hook_ownership.py Canonical read-only ownership inspection; preserve ordinary excluded-target cleanup.
commands/uninstall/cli.py Preserve both native cleanup paths and empty-lock retry; import the existing lightweight lock-state owner without increasing the statement budget.
.apm/architecture/owners/marketplace-plugins.json, architecture linter/tests Union both native owners and static mutation catalogs, including selected-format exclusion.
Claude component/installed-CLI tests, Codex lifecycle tests Real routing and lifecycle regressions; existing Codex inline-MCP fixture now selects both targets. Claude metadata transport remains substituted.
tests/spec_conformance/test_claude_cleanup_roots.py, CONFORMANCE.* Five retained-hook preservation cases and statements regenerated from the complete merged collection.
Consumer/producer/reference docs and apm-usage/commands.md Exact scope, admission, activation ownership, recovery and unresolved runtime qualification.

Source paths above are under src/apm_cli/ unless otherwise qualified.
The Claude reconciliation owner is the only Claude native lifecycle writer.
The generic source-plan seam and native hash API/tests are inherited from canonical main, not duplicated.

Diagrams

For an eligible Claude-format plugin, dashed stages show metadata writes after shared gates; failure retains intent rather than promising rollback.

flowchart LR
    subgraph Shared["Shared APM admission"]
        A["Resolved identity, target and executable approval"] --> B["plan_native_claude_plugin and fingerprint"]
        B --> C["DeployableSourcePlan scan and retained-hook refusal"]
    end
    subgraph Native["Native metadata only"]
        D["Saved lock, source pin and pre-write fingerprint"] --> E["Write recoverable catalog and intent"]
        E --> F["Claude metadata install, update or uninstall"]
        F --> G["Readback roots, activation and fingerprint"] --> H["Finalize owned ledger"]
        R["Retain intent and report failure"]
    end
    C --> D
    F -->|"metadata failure"| R
    G -->|"mismatch"| R
    classDef new stroke-dasharray: 5 5;
    class B,D,E,F,G,H,R new;
Loading

Trade-offs

  • Metadata qualification, not runtime support: exact Claude 2.1.291 user/global route; no fallback for unqualified versions or missing native consent.
  • Complete native unit, not legacy hash equivalence: original local-source lock hashes and complete installed-native fingerprints remain separate. Claude audit uses its dedicated verifier without creating loose deployment claims.
  • Recovery, not external rollback: retain intent and fail visibly; explicit removal is required for unsafe legacy transitions.
  • Faithful compatibility, not unrelated redesign: do not bypass canonical source detection using unproven lock-kind equivalence or add cross-dependency partial-delivery behavior.
  • Substitution is disclosed: Claude installed-CLI cases replace external metadata transport; approved official Codex cases exercise metadata/content only, not inference or MCP execution.

Benefits

  1. Three hook descriptors and indirect resources remain intact without loose Claude projection.
  2. New registrations remain disabled while existing enabled/disabled choices survive updates.
  3. Last-package cleanup can retry from saved authoritative survivors.
  4. Same-pin byte/mode drift is refused, read-only audit preserves state, and both selected formats retain their own lifecycle owner.

Issue and approved scope

Issue: Related #3191; shared production foundation for separately scoped #3181.

Human scope-approval comment: #3191 (comment)

Companion scope-approval comment: #3181 (comment)

Fresh immutable trusted-main7e20 governance recognizes the records but explicitly returns authorizes_implementation:false.
Current responsible-human dispatch authorizes this same-owner compatibility repair and qualified draft publication; labels/records alone are not permission.

This PR does not complete the issue. Actual three-event witnesses, effective runtime roots/resources and final native qualification remain unmet.
#3181 alone owns runtime investigation; its prior PTY stopped at normal security consent without trust, enablement or invocation.
No reviewer request, draft promotion, auto-merge, issue closure or runtime-acceptance waiver is made.

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Maintenance / refactor

Testing

  • Tested locally
  • All existing tests pass
  • Added tests for new functionality (if applicable)

Validation

Revival at ea99d5fab (2026-11-12): merged main a14ee1521; full lint mirror clean; 9346 related + 2116 fold-rerun + 29 #3291 tests passed; CI, Spec conformance and Merge Gate green. Details: advisory. Sections below are the earlier qualification record.

Published head: d23d1acca67e569352ae89022f0cc8fcb7e42f31; integrated main: 7e20e044fb501c90279a325a278b69a72ad63367.
This merge preserves public 0d4ee809 ancestry and the same PR/branch. The command companion #3291 consumes this public pin, not a private patch.

Resumed integration evidence Observed result
Merged working-tree functional selection 424 passed, including six installed-CLI lifecycle variants: three local and three pinned-Git.
Merged working-tree static owner selection 120 passed.
Full conformance collection 517 passed, 2 skipped; orphan check and generated statements passed.
Committed-head functional owner bindings 46 passed, covering all 8 detected owners at d23d1acca.
Committed-head full current lint mirror Ruff, format, three source guards, pylint R0801, auth, architecture, strict assertions and exact-test duplicates passed.
Four process-memory regression mutations 10 intended failures, zero errors; guards restored before the passing functional selection.

The broad runs used the complete merged working tree before the merge commit; they are not exact-head 0d4ee809 results. Exact-head bindings and the full mirror ran after committing d23d1acca, with a clean tree before and after.
The source guards use disclosed stdlib equivalents of CI's GNU-grep YAML/relative-path checks and its 2100-line check, not unsupported macOS grep.
Actual completion remains blocked on native acceptance. The blocked completion path does not run terminal-owner enforcement; executed owner bindings are not a readiness verdict.

CI was green at d23d1acca: CI attempt 2, Spec conformance and Merge Gate attempt 2 completed success. The first lifecycle attempt printed 394 passed, 13 skipped in 577.43s, then hit the unchanged 10-minute job deadline; its isolated retry passed in 511.37s, with a 9:05 total job duration. Original cancellation evidence remains. No timeout, selection or source change was made; cumulative CI recoveries are now 3, with historical 6/3/2 preserved separately.

Resumed commands and bounded review

All heavy commands used the parent's automatic lane3191 capacity gate.
The retained resume7e20-validate.py qualification receipt records exit 0: underlying pytest selectors produced 424/120/517 passing cases, followed by passing orphan check and generation.
The retained resume7e20-exact.py receipt records exit 0: exact selectors produced 46 passes, followed by the full current lint scope and strict guards.
The retained mutation receipt records exit 0: projection/local-hash/MCP-snapshot/replay-root mutations produced 1/1/4/4 test failures, with no setup/import errors.
uv run --frozen --extra dev ruff check src/ tests/ scripts/lint_architecture_boundaries.py scripts/architecture_linter/ scripts/windows_native_symlink_probe_entry.py: exit 0.
uv run --frozen --extra dev ruff format --check src/ tests/ scripts/lint_architecture_boundaries.py scripts/architecture_linter/ scripts/windows_native_symlink_probe_entry.py: exit 0, 2093 files already formatted.
uv run --frozen --extra dev python -m pylint --disable=all --enable=R0801 --min-similarity-lines=10 --fail-on=R0801 src/apm_cli/ scripts/lint_architecture_boundaries.py scripts/architecture_linter/ scripts/windows_native_symlink_probe_entry.py: exit 0.
bash scripts/lint-auth-signals.sh and bash scripts/lint-architecture-boundaries.sh: each exit 0.
CI with APM_E2E_TESTS=1: uv run --extra dev pytest -p no:cacheprovider -q --strict-markers -n 4 --dist loadgroup --durations=20 -m 'lifecycle_smoke and not lifecycle_merge_group' tests/integration: exit 0 on retry, 394 passed / 13 skipped.
BASE_REF=origin/main bash tests/spec_conformance/mode_b_detector.sh: exit 0; spec-concurrent path delegates to the passing orphan check.
The preserved Mermaid diagram was rendered with mmdc: exit 0; extracted diagram bytes match the body.
The session-owned drivers retain each exact underlying command, JUnit/log hash and recorded revision. No native client or inference was launched.
Bounded architect and coverage reviews found no required findings in their reviewed deltas; final canonical-validator/replay adjustments were subsequently qualified, not represented as a new full-panel approval.

Historical qualification at 0d4ee80

Prior published head: 0d4ee8095f43c241995b30c5c3b83a3c4fe50f0b; integrated base: 53ccf06d11dd2d675e8ea8c3e2523a6d321c1b79.
Ancestry preserves the prior Claude head e69283b and landed Codex main53. No rebase, force push or superseding PR.

Exact-head evidence Observed result
Focused Claude/Codex/owner/quality suites 610 passed, including 68 quality cases and six installed-APM Claude variants.
Combined static regression selection 31 passed.
Existing official Codex 0.163 metadata/content lifecycle 6 passed, including both-target inline fixture; isolated credential-free profiles.
Full conformance 348 passed, 2 skipped; orphan check, generation, Mode B and clean statements passed.
Actual post-mutation restoration 81 failed test IDs passed again; source bytes and tracked tree unchanged.
Current CI lint scope plus strict guards All 10 passed, including scripts/windows_native_symlink_probe_entry.py.
Detected owners / executed bindings 5 owners / 13 executed passing IDs with exact head/base and JUnit hashes.

These suites overlap; their counts are not a unique repository-wide total.
The actual completion status remains blocked, so canonical verify_completion skips terminal-owner enforcement. The separately disclosed advisory-status projection is an architecture-only probe, not an actual terminal gate or readiness pass; the five-owner/13-ID row above describes executed bindings only.

Executed commands and results

APM_QUALIFICATION_OUTPUT=../pr-3290-evidence/continuation-6-main53/candidate-3 uv run --frozen --extra dev python ../pr-3290-evidence/continuation-6-main53/run_functional.py ran the recorded affected-test selectors and full conformance: exit 0.

610 passed, 1 warning in 236.80s (0:03:56)
31 passed, 478 deselected in 92.07s (0:01:32)
6 passed in 79.72s (0:01:19)
348 passed, 2 skipped in 216.36s (0:03:36)

uv run --frozen --extra dev python ../pr-3290-evidence/continuation-6-main53/restore_mutants.py: exit 0.

81 passed in 189.84s (0:03:09)

APM_QUALIFICATION_OUTPUT=../pr-3290-evidence/continuation-6-main53/candidate-3/mirror-before-functional uv run --frozen --extra dev python ../pr-3290-evidence/continuation-6-main53/run_mirror.py: exit 0.
This executes all eight actual CI lint blocks unchanged, then strict assertion and exact-duplicate guards; all ten passed.
uv run --frozen --extra dev python -m tests.spec_conformance.orphan_check: exit 0.
uv run --frozen --extra dev python -m tests.spec_conformance.gen_statement: exit 0.
BASE_REF=origin/main bash tests/spec_conformance/mode_b_detector.sh: exit 0.
git diff --exit-code CONFORMANCE.json CONFORMANCE.md: exit 0.
These session-owned evidence drivers are not repository commands; their receipts retain each exact underlying selector, environment and JUnit hash.
The unchanged diagram was rendered again with mmdc, exit 0.

Mutation proof: 16 Claude/shared guard removals produced 40 intended failures; 41 unchanged producer Codex/API mutants produced 46 test-call failures; two additional static guard disablings produced 15 failures. Every failed ID maps to the actual 81-case post-restoration run. Five Codex failures are downstream contract exceptions, not literal AssertionErrors; none are setup/import errors or skips. Shared API source bytes were never edited, although producer guards were intentionally disabled in process memory.

Independent delta review: seven specialists reviewed the frozen initial merge tree; later folds and the final import/whitespace repairs were separately qualified at this exact head. Genuine CEO stance is ship_with_followups for qualified draft publication, not merge or runtime acceptance. Lazy phase import and existing both-target lifecycle coverage were folded. The proposed loose projection from an opaque Codex bundle was rejected; unproven replay optimization and cross-dependency failure isolation remain outside scope. Original returns and factual/coordinator corrections are retained, not rewritten.

Historical remote CI: exact-head REST verification confirmed CI 39470640291, Spec conformance 39470640316 and Merge Gate 39470640367 completed success for 0d4ee809. These are not CI results for the resumed head. CI jobs included both Linux shards/Coverage, Windows gates, lint, architecture and APM/lifecycle/binary smoke. CodeQL, Docs, NOTICE and eligibility workflows also succeeded. Original yellow-CI receipts remain untouched; this is additive evidence, not native, specification or release readiness. The historical e69283b results and prior needs_discussion stance are not relabelled.

Preserved history: failed 6d7d920 native whitespace assertion, cdde876 statement-budget failure, initial post-push readback failure and all earlier receipts remain. Historical counters at 0d4ee809 were 6/3/2, validated using the explicitly authorized session-only budget variant; no repository schema change or count reset. The resumed retry is reported separately above.

API provenance: original producer utility 5267a126 / tests 04cd8c9 were privately imported with authorship as af061529 / f3ff7a1e. They are now canonical on merged main53 and byte-identical. This continuation intentionally integrates landed Codex behavior; it does not claim only the historical API patches were imported.

Audit/runtime boundary: the prior raw-local MCP consistency failure is fixed at d23d1acca; local frozen install and aggregate audit now pass the installed-CLI contract with substituted metadata transport. Historical real Claude 2.1.291 registrar evidence remains metadata-only and was not rerun. POSIX executable evidence is not new Windows runtime qualification.

Scenario Evidence

Scenario Principle Executed test
Intact hooks/resources without loose Claude projection Multi-harness support tests/unit/install/test_claude_native_hooks.py::test_native_hooks_remain_intact_without_loose_settings
Retained owned/unreadable hook state refuses native transition without deletion Secure by default tests/spec_conformance/test_claude_cleanup_roots.py::test_native_transition_preserves_retained_target_hook_state (five cases)
Missing approval, unsafe tree and actual skill subsets refuse admission Governed by policy tests/unit/install/test_claude_native_hooks.py::test_hook_denial_does_not_register_a_commands_only_subset; tests/unit/install/test_claude_native_admission.py
Full byte/mode fingerprint, same-pin refusal and read-only audit Secure by default tests/unit/install/test_claude_native_registration.py::test_complete_native_bundle_drift_is_not_legacy_hash_equivalence; same file's test_local_native_audit_checks_source_and_live_cache_without_repairing_either
Removal/retry and original ownership survive failures DevX tests/unit/install/test_claude_native_registration.py::test_legacy_native_ownership_requires_explicit_removal_before_attestation; tests/integration/test_claude_native_hook_lifecycle.py::test_installed_hook_source_reinstall_and_removal
Both targets preserve native-format ownership Multi-harness support tests/unit/install/test_claude_native_hooks.py::test_native_admission_keeps_selected_format_owner_with_both_targets; tests/integration/test_codex_native_plugin_lifecycle.py::test_installed_cli_registers_complete_codex_bundle_disabled[inline]
A same-name personal loose skill survives native install and removal DevX tests/unit/install/test_claude_native_hooks.py::test_prepared_native_plan_preserves_unmanaged_loose_skill; six installed lifecycle variants
Local plugin MCP inspection preserves publisher bytes and never waives a missing synthesized manifest Secure by default tests/unit/integration/test_mcp_config_view.py::test_local_claude_source_is_never_mutated_or_waived_during_mcp_inspection (eight cases)
Local source hashes and native-cache tampering are checked independently Secure by default tests/unit/install/test_claude_native_registration.py::test_local_lock_hash_and_admitted_cache_fingerprint_are_independent; local audit tamper cases

How to test

  • Inspect the exact recorded commands/JUnit under the candidate evidence root; they exercise real APM while clearly separating substituted Claude metadata and existing official Codex metadata routes.
  • Run the corresponding focused files and full tests/spec_conformance with workspace-owned fixture paths; expect the results above.
  • Run the current CI lint blocks and strict quality guards without raising budgets or suppressing assertions.
  • Check the real mutation/restoration receipts, preserved failures, source hashes and exact owner bindings.
  • Leave native acceptance pending with [BUG] ${CLAUDE_PLUGIN_ROOT} is rewritten in hooks but not in commands #3181; this description does not authorize trust, activation, invocation or another native probe.

Spec conformance (OpenAPM v0.1)

If this PR changes behaviour that an OpenAPM v0.1 req-XXX covers,
confirm the three-step ritual in the
development guide:

  • Spec edit: docs/src/content/docs/specs/openapm-v0.1.md updated
    (new/changed <a id="req-XXX"></a> anchor + prose + Appendix C
    row).
  • Manifest edit: docs/src/content/docs/specs/manifests/openapm-v0.1.requirements.yml
    updated.
  • Test edit: a @pytest.mark.req("req-XXX") test under
    tests/spec_conformance/ added or extended.
  • CONFORMANCE.{md,json} regenerated via
    uv run --extra dev python -m tests.spec_conformance.gen_statement
    and committed.
  • N/A -- this PR does not change OpenAPM-observable behaviour.

Not N/A: observable behavior changes, but this repair preserves existing target, selection, integrity, authorization, retained-hook and canonical source-plan constraints.
The retained-hook transition complies with req-lk-021; no normative waiver is required.
Five executable preservation cases cover owned state, orphaned ownership, malformed config/sidecar and non-object JSON. Statements were regenerated from the complete collection.
The native fingerprint is target-specific ownership metadata; ordinary lock hashing remains canonical. Claude replay uses its complete verifier instead of copying source into loose deployment roots. No normative text or manifest changes were authored by this PR.
req-tg-013 remains schema-bearing Agent Plugins v1 only; raw Claude metadata does not claim that atomic-registration contract. Implementation-specific external formats are not exempt from consumer safety.

Remaining acceptance boundary: actual Claude runtime witnesses and consent are absent. Neither conformance, metadata qualification nor CI authorizes draft promotion, issue closure or merge.

Co-authored-by: Copilot [email protected]

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Daniel Meppiel (danielmeppiel) added 5 commits October 20, 2026 11:54
@danielmeppiel
feat: prepare intact Claude plugins through native user registration
3e9a837
Register new plugins disabled via the qualified native CLI, preserve activation, and reconcile owned metadata from locked sources. Authenticated runtime qualification remains pending.

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: 6c656434-efdf-444d-bb89-27407cbc7c44
@danielmeppiel
fix: retain normalized plugin identity and canonical native routing
4a34515
Read saved lock state, preserve parser-normalized legacy plugin types, and retain selector/preflight ownership while suppressing loose projection.

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: 6c656434-efdf-444d-bb89-27407cbc7c44
@danielmeppiel
Merge remote-tracking branch 'origin/main' into danielmeppiel-native-…
4d615ca
…hook-delivery
@danielmeppiel
test: qualify native hook routing and consent-preserving lifecycle
ca8d32b
Cover user-hook migration, standalone and replay controls, full-source safety, interrupted ownership recovery and native transport metadata exclusion. Document qualified metadata versus pending runtime execution.

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: 6c656434-efdf-444d-bb89-27407cbc7c44
@danielmeppiel
fix: require locked native plans and honor complete skill selection
4f21630
Co-authored-by: Copilot App <[email protected]>

Copilot-Session: 6c656434-efdf-444d-bb89-27407cbc7c44
@danielmeppiel Daniel Meppiel (danielmeppiel) self-assigned this Oct 20, 2026
@danielmeppiel Daniel Meppiel (danielmeppiel) mentioned this pull request Oct 20, 2026
test(claude): protect native command context and lifecycle #3291
Draft
5 of 16 tasks
Daniel Meppiel (danielmeppiel) and others added 11 commits October 20, 2026 13:52
@danielmeppiel
fix(claude): preserve native recovery and child environment
dcf6452
Fold independent PR3290 panel findings and observed CI failures. Exercise installed APM hook metadata lifecycle without native hook execution. Preserve canonical empty survivors until native cleanup succeeds, keep target-aware diagnostics, and document the missing runtime witnesses.

Metadata protocol fixture extracted from Daniel Meppiel's command lifecycle test in commit 41bdcf1, preserving its metadata-only boundary.

Co-authored-by: Daniel Meppiel <[email protected]>

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
Merge current main into native Claude convergence
590ca0e
Co-authored-by: Copilot App <[email protected]>

Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a

# Conflicts:
#	src/apm_cli/install/drift.py
@danielmeppiel
Merge test-only main advance into native Claude convergence
108b1cc
Co-authored-by: Copilot App <[email protected]>

Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
Merge main 45afc01 into Claude native delivery
09fc232
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
fix(claude): preserve retained loose hooks before native admission
0be44e0
Refuse unsupported automatic migration through the existing hook owner.
Exercise req-lk-021 byte preservation and malformed-state refusal with
real component conformance cases; keep native runtime qualification open.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
Merge main 942a332 audit target ownership into Claude delivery
907ee2f
Preserve retained-hook compliance and the canonical native replay seam.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
feat: add opt-in full native bundle fingerprint
af06152
Keep existing package and lockfile hash semantics unchanged. Provide one canonical raw-content and Git executable-bit fingerprint for native consumers.

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
test: qualify canonical opt-in native fingerprint contract
f3ff7a1
Exercise complete publisher assets, Git executable bits, transport exclusions, symlink refusal, and unchanged historical package hashes without any native runtime.

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
fix: attest complete Claude native resources and replay ownership
84575c7
Use the sole canonical native fingerprint API for admission, retained ownership, readback and read-only audit. Bind remote attestations to saved source pins, refuse unfingerprinted legacy adoption, and retain recoverable removal intent. Normalize local replay inputs only in scratch.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
test: fold independent native fingerprint lifecycle review
8927db4
Exercise missing pins, independently callable pre-write checks, mixed-version removal recovery, normalization stability and real local CLI audit. Keep the pre-existing local MCP consistency diagnostic distinct from native drift evidence. Document audit scope and retained fingerprint boundaries.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
docs: distinguish local audit consistency from native drift
e69283b
Fold the independent CEO synthesis follow-up without weakening the generic MCP source-admission contract. Raw local legacy plugins can retain a separate config-consistency failure while their native fingerprint is healthy.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel

Daniel Meppiel (danielmeppiel) commented Oct 20, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator Author

APM Review Panel: ship_with_followups - qualified draft publication only

DRAFT / NATIVE ACCEPTANCE HOLD. Actual Claude SessionStart, SubagentStart and UserPromptSubmit witnesses and native consent remain absent. Successful CI is not native, specification or release readiness. Keep PR3290 draft and issue3191 open.

Current head: 0d4ee8095f43c241995b30c5c3b83a3c4fe50f0b; integrated base: 53ccf06d11dd2d675e8ea8c3e2523a6d321c1b79.
This ancestry-preserving continuation integrates landed Codex behavior with the prior Claude foundation. It preserves separate native registrars, queues, ledgers, canonical source-plan/hash ownership and default hashing semantics.

Independent delta disposition

Seven genuine specialists reviewed the frozen initial merge tree: architecture, supply-chain, coverage, performance, DevX, documentation and authentication. Later folds were separately qualified at the exact published head. The genuine CEO stance is ship_with_followups for qualified draft publication, not permission to merge.

  • Folded lazy Claude phase loading and existing both-target installed-CLI lifecycle coverage.
  • Preserved both native/static catalogs and retained-hook conformance; fixed only the merged statement budget and wrapped-output assertion without weakening their contracts.
  • The CEO rejected proposed loose projection from an opaque Codex bundle because it contradicts canonical suppression of all loose projections.
  • Retained factual corrections: e69283b was the earlier Claude head, not Codex; remote CI was observed after publication, not before it. Original specialist/CEO returns remain preserved. No new panel ran for this metadata closeout.

Exact-head qualification

610 focused tests (including 68 quality cases), 31 static cases, six existing official Codex metadata/content cases, and 348 conformance cases passed; two conformance cases skipped. All ten local lint/architecture/strict guards passed.

Sixteen Claude/shared mutations produced 40 failures; 41 producer Codex/API mutants produced 46 test-call failures; two additional static disablings produced 15. All 81 distinct failed IDs passed after restoration. Five Codex failures are downstream contract exceptions, not literal assertions; none are setup/import errors or skips. API source bytes remained unchanged; in-memory mutations are disclosed.

Owner precision: five deterministically detected owners map to 13 executed current-head functional IDs. Actual completion status remains blocked, so canonical verify_completion skips terminal-owner enforcement. The separately disclosed advisory-status projection is an architecture-only probe, not an actual terminal gate or readiness pass.

Observed CI

Fresh exact-head REST reads confirm successful CI 39470640291, Spec conformance 39470640316 and Merge Gate 39470640367. CI job evidence includes both Linux shards/Coverage, Windows gates, lint, architecture and APM/lifecycle/binary smoke. CodeQL, Docs, NOTICE and eligibility workflows also succeeded.

Original yellow-CI completion, validation, publication and handoff receipts remain untouched. This green observation is additive; historical e69283b results and its needs_discussion stance are not relabelled.

Remaining boundaries

#3181 alone owns native runtime investigation under the existing consent boundary. Metadata responses and substituted Claude transport do not supply runtime witnesses. No new trust, activation, credential use or native action occurred.

Unproven replay optimization, cross-dependency failure isolation and unrelated raw-local missing-manifest MCP consistency remain outside this repair. Native acceptance itself is still an unmet original criterion, not deferred or waived.

Cumulative counts remain 6 outer / 3 Copilot rounds / 2 CI recoveries, under the authorized session-only budget override. This metadata closeout adds no iteration or recovery. GitHub reports MERGEABLE / BLOCKED; the PR remains draft/open, with no auto-merge, reviewer request, merge or issue closure.


Generated by autopilot-pr-merge-worker. This comment is AI-generated and may contain errors.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Daniel Meppiel (danielmeppiel) and others added 4 commits October 20, 2026 19:15
@danielmeppiel
Merge main53 native Codex foundation without crossing Claude ownership
6d7d920
Preserve both native registrars, selected-format admission, audit replay and cleanup. Retain canonical native hashing and source-plan authority; cover combined target selection and defer the Claude phase import.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
test: preserve Codex refusal assertion across wrapped diagnostics
cdde876
The exact merged candidate emitted the required user-scope refusal, but Rich wrapped the phrase across a line. Normalize diagnostic whitespace while retaining the failure, wording and unchanged-native-state assertions.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
refactor(uninstall): import the lightweight lock-state owner once
0d4ee80
Keep dynamic function lookup through the existing pure lockfile_state owner. This removes a redundant function-local import and restores the unchanged 200-statement budget after the native merge, without changing cleanup or refusal behavior.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
@danielmeppiel
Merge main and preserve canonical Claude native deployment
d23d1ac
Share prepared native admission with batch skill preflight, verify local locks against the original source image, and inspect raw local MCP declarations in disposable validated snapshots. Keep Claude audit verification isolated from loose deployment replay and preserve independent cache fingerprints.

Co-authored-by: Copilot App <[email protected]>

Copilot-Session: 6c656434-efdf-444d-bb89-27407cbc7c44
Daniel Meppiel (danielmeppiel) added a commit that referenced this pull request Oct 21, 2026
@danielmeppiel
Merge public native plugin foundation into command qualification
4c9039e
Integrate published #3290 d23d1ac and main 7e20 while preserving the independent #3181 command contracts and contributor ancestry. Native runtime acceptance remains unmet; this merge does not grant consent.

Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 583dd1bc-30be-41e1-b45e-a1dd8988136e
@danielmeppiel

Daniel Meppiel (danielmeppiel) commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator Author

Published d23d1acca67e569352ae89022f0cc8fcb7e42f31 on this same draft PR, preserving 0d4ee809 ancestry and merging main 7e20e044.

The resumed repair shares native admission with batch skill preflight, preserves same-name personal loose skills, checks local locks against original source snapshots, validates raw local MCP declarations in disposable scratch, and keeps complete Claude audit verification out of loose-deployment replay. The command companion #3291 consumed this public foundation; no private producer patch was required.

Evidence: 424 functional and 120 static passes on the merged working tree; full conformance 517 passed / 2 skipped; 46 exact-head functional cases bind all 8 detected owners; full current lint mirror and strict guards pass. Four process-memory guard mutations produced 10 intended failures with zero errors before restoration.

Current CI, spec conformance, and Merge Gate are successful at this head. The original lifecycle job completed 394 tests successfully, with 13 skips, then hit its 10-minute job deadline. Its one isolated retry passed in 511.37 seconds / 9:05 total job time. No timeout, selection or source was changed. The original cancellation remains recorded; historical 6/3/2 is preserved, with cumulative CI recoveries now 3.

Acceptance remains blocked, not ready to merge. Normal native consent for the isolated owned fixture session is still absent. Actual Claude Code 2.1.291 SessionStart, SubagentStart and UserPromptSubmit execution, distinct effective roots/resources, and runtime lifecycle-state witnesses must follow that consent through the designated runtime owner. No native probe, trust bypass or activation occurred here. Metadata, substituted transport, conformance and green CI do not replace those witnesses. Keep this PR draft and #3191 open; final qualification/merge stays with the coordinating maintainer.


Generated by autopilot-pr-merge-worker. This comment is AI-generated and may contain errors.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@danielmeppiel Daniel Meppiel (danielmeppiel) mentioned this pull request Nov 12, 2026
feat(hooks): stage consent-aware Claude standalone inline hooks #3332
Draft
8 of 25 tasks
Daniel Meppiel (danielmeppiel) and others added 3 commits November 12, 2026 09:40
@danielmeppiel
Merge origin/main into danielmeppiel-native-hook-delivery
0d8c0b5
Resolve two conflicts while keeping main's behavior and this PR's native
Claude registration owner:

- uninstall: keep main's _persist_uninstall_lockfile (symlink refusal,
  committed-claim binding, profile-scoped updates) and extend it with
  defer_empty_removal so an empty last-package lock is still retained until
  Claude native cleanup converges, then removed.
- mcp_config_view: adopt main's #3540 redirect to the install-synthesized
  apm_modules/_local manifest for local Claude plugins (with missing-manifest
  warning and frozen cold-cache deferral). Drop the superseded scratch
  snapshot and retarget the marketplace-integrations-claude-ownership
  static guard and its mutation cases to main's redirect.

Co-authored-by: Copilot App <[email protected]>
@danielmeppiel
fix(claude): keep main's lock owner and budgets after merging main
e61a6c5
- Route uninstall lock persistence through main's guarded
  _persist_uninstall_lockfile call; a small helper persists survivors,
  converges native registrations, then removes an empty last-package lock,
  keeping uninstall() within its statement budget.
- Extract _queue_native_claude so integrate_package_primitives stays
  within the C901 limit after combining main's changes.
- Align the local Claude MCP read-only test with main's #3540 semantics:
  without the install-synthesized manifest, servers stay uncollected and the
  publisher source is never mutated.

Co-authored-by: Copilot App <[email protected]>
@danielmeppiel
fix(claude): name native resync inputs and trap deferred lock removal
ea99d5f
Fold delta-panel follow-ups on the merge resolution:

- _persist_lock_then_resync_native takes deploy_root, modules_dir and
  scope explicitly instead of forwarding **kwargs.
- Unit traps for _persist_uninstall_lockfile defer_empty_removal branches
  and for removing an empty last-package lock only after native resync
  converges (mutation-break: no-defer -> 3 failures, unlink-before-resync
  -> 2 failures).

Co-authored-by: Copilot App <[email protected]>
@danielmeppiel

Daniel Meppiel (danielmeppiel) commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator Author

Native Claude check (10 minutes)

This is the merge gate for #3181: Claude Code itself must load the plugin APM registered and run its namespaced command, with ${CLAUDE_PLUGIN_ROOT} resolving to the intact plugin. An agent cannot pass Claude's trust prompt, so this needs one human run. Everything happens in a throwaway HOME, so your real ~/.claude and ~/.apm are not touched.

Requirements: macOS or Linux, git, node + npm, uv, python3, and a Claude login (or ANTHROPIC_API_KEY). The fixture is the #3291 plugin tests/fixtures/native_claude_commands: its manifest selects one command, selected/status.md, which runs node "${CLAUDE_PLUGIN_ROOT}/scripts/context.mjs", which reads a bundled resource file.

1. Isolated tools (about 3 minutes)

export CHECK="$(mktemp -d /tmp/apm-native-claude-check.XXXXXX)"
export SHA="$(git ls-remote https://github.com/microsoft/apm refs/heads/danielmeppiel-claude-command-qualification | cut -f1)"
echo "check dir: $CHECK  stack head: $SHA"

# Claude Code 2.1.291 is the only version APM's native route is qualified for.
npm install --silent --prefix "$CHECK/npm" @anthropic-ai/[email protected]
# APM from the #3290 + #3291 stack head.
if ! { uv venv -q "$CHECK/apm-venv" && uv pip install -q --python "$CHECK/apm-venv/bin/python" "git+https://github.com/microsoft/apm@$SHA"; }; then
  # Fallback if uv cannot resolve from your index: run the stack source with
  # the .venv of an existing microsoft/apm checkout.
  export APM_REPO="$HOME/Repos/awd-cli"
  git -C "$APM_REPO" fetch -q origin danielmeppiel-claude-command-qualification
  git -C "$APM_REPO" worktree add -q --detach "$CHECK/apm-src" "$SHA"
  mkdir -p "$CHECK/apm-venv/bin"
  printf '#!/bin/sh\nPYTHONPATH="%s/apm-src/src" exec "%s/.venv/bin/python" -m apm_cli.entrypoint "$@"\n' "$CHECK" "$APM_REPO" > "$CHECK/apm-venv/bin/apm"
  chmod +x "$CHECK/apm-venv/bin/apm"
fi
"$CHECK/apm-venv/bin/apm" --version   # the version line ends with the first 9 chars of $SHA

2. Isolated HOME and CLAUDE_CONFIG_DIR

export REAL_HOME="$HOME"
export HOME="$CHECK/home"
export CLAUDE_CONFIG_DIR="$CHECK/home/.claude"
export PATH="$CHECK/npm/node_modules/.bin:$CHECK/apm-venv/bin:$PATH"
mkdir -p "$HOME/.apm" "$CHECK/work"
claude --version     # expect: 2.1.291 (Claude Code)

3. Install the fixture plugin globally with APM

cat > "$HOME/.apm/apm.yml" <<EOF
name: native-claude-check
version: 1.0.0
targets: [claude]
dependencies:
  apm:
    - git: microsoft/apm
      ref: $SHA
      path: tests/fixtures/native_claude_commands
EOF
(cd "$CHECK/work" && apm install -g --target claude --only apm)

Expected output includes:

1 native Claude plugin(s) registered; existing activation preserved. New plugins
are disabled. Review and enable them in Claude; restart or reload plugins there.
claude plugin list --json
ls "$CLAUDE_CONFIG_DIR/commands" 2>&1    # expect: No such file or directory (no loose copies)

Expected: exactly one entry, "id": "apm-command-context@apm-claude", "scope": "user", "enabled": false, with readFromFolder ending in .apm/apm_modules/microsoft/apm/tests/fixtures/native_claude_commands.

4. Your consent: enable the plugin

APM never enables plugins. You do that:

claude plugin enable apm-command-context@apm-claude --scope user

5. Run the namespaced command in a real session

cd "$CHECK/work"
APM_COMMAND_PROBE_MARKER="$CHECK/witness.jsonl" claude

In Claude:

  1. Accept the folder trust prompt and log in if asked (the config is fresh).
  2. Type /apm-command-context:. The menu must offer status and must NOT offer unselected.
  3. Run /apm-command-context:status qualified-3181. Approve the node command if Claude asks.
  4. Claude prints JSON like this. The root is your $CHECK path, so it will differ:
{"root":"<CHECK>/home/.claude/plugins/cache/apm-claude/apm-command-context/1.0.0","resource":"APM_NATIVE_COMMAND_CONTEXT","argument":"qualified-3181"}
  1. Type /exit.

6. Verify the witness (proof of success)

python3 - "$CHECK" <<'PY'
import json, pathlib, sys
check = pathlib.Path(sys.argv[1]).resolve()
rows = [json.loads(l) for l in (check / "witness.jsonl").read_text().splitlines() if l.strip()]
assert len(rows) == 1, rows
row = rows[0]
assert row["resource"] == "APM_NATIVE_COMMAND_CONTEXT", row
assert row["argument"] == "qualified-3181", row
root = pathlib.Path(row["root"]).resolve()
assert root.is_relative_to(check / "home"), root
assert (root / "scripts/context.mjs").is_file() and (root / "resources/identity.txt").is_file(), root
print("[+] NATIVE CLAUDE CHECK PASSED")
print("    root:", root)
PY

Success means the script prints [+] NATIVE CLAUDE CHECK PASSED, Claude showed the same JSON, and the menu had status but no unselected. Paste the two printed lines plus the claude plugin list --json output into this PR.

Failure looks like one of these: /apm-command-context:status is missing from the menu, unselected is offered, the JSON has an empty or wrong resource, root is outside $CHECK/home, or the witness file is missing. If Claude printed the JSON but no witness file exists, paste the JSON anyway; the env var may not reach the command shell.

Heads-up from the agent dry run: claude plugin details apm-command-context@apm-claude reports Skills (0). A plain plugin with no APM involved shows the same thing when its command is declared through a manifest commands path, while default commands/ files are counted. That could be a details blind spot or a real loading gap. This step settles it.

7. Clean up

(cd "$CHECK/work" && apm uninstall -g microsoft/apm/tests/fixtures/native_claude_commands)
claude plugin list --json      # expect: []
export HOME="$REAL_HOME"; unset CLAUDE_CONFIG_DIR
[ -n "${APM_REPO:-}" ] && git -C "$APM_REPO" worktree remove --force "$CHECK/apm-src"
rm -rf "$CHECK"

Then open a new shell so PATH is clean again.

What the agent already verified at stack head 73a2550d0 (no trust, enable, or session): with real Claude 2.1.291 and an isolated HOME and CLAUDE_CONFIG_DIR, step 3 registered apm-command-context@apm-claude disabled at user scope, created no loose commands, and step 7 removed the registration and the empty lock. On this machine the uv pip install path failed to resolve dependencies, and the step 1 fallback worked.


Generated by autopilot-pr-merge-worker. This comment is AI-generated and may contain errors.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@danielmeppiel

Daniel Meppiel (danielmeppiel) commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator Author

APM Review Panel (delta): needs_discussion - revived, waiting on the native Claude check

Daniel decided on 2026-11-12 to revive #3290 and #3291. This run brought them up to date with main. Code, lint and CI are green. Merging still needs the #3181 proof that Claude Code actually loads and runs the command; agents cannot pass Claude's trust prompt. Daniel's 10-minute script: #3290 (comment)

What changed in this run

  • Merged current main (a14ee1521, 145 commits) into fix(claude): prepare intact user plugins through native registration #3290. Two conflicts:
    • commands/uninstall/cli.py: kept main's guarded _persist_uninstall_lockfile (symlink refusal, claim binding, profile-scoped updates). It now writes an empty last-package lock instead of deleting it right away. _persist_lock_then_resync_native deletes that lock only after Claude native cleanup succeeds, so an interrupted removal can still retry.
    • integration/mcp_config_view.py: switched to main's fix(mcp): deploy MCP servers from local-path Claude plugin dependencies #3540 behavior, which reads the install-synthesized apm_modules/_local manifest, warns when it is missing, and defers under a frozen cold cache. Removed the PR's scratch-snapshot path. Moved the marketplace-integrations-claude-ownership guard and its mutation cases onto main's redirect, and aligned one unit test with main's semantics. The publisher source is still never written.
  • Extracted _queue_native_claude so integrate_package_primitives stays within C901 50 after the merge.
  • Restacked test(claude): protect native command context and lifecycle #3291 cleanly: its diff against fix(claude): prepare intact user plugins through native registration #3290 is still exactly its 8 test, fixture and doc files.

Folded in this run

  • (panel) python-architect: _persist_lock_then_resync_native now takes deploy_root, modules_dir and scope explicitly instead of **kwargs -- resolved in ea99d5f.
  • (panel) test-coverage-expert: added unit traps for the deferred empty-lock branches and for deleting the lock only after native resync converges -- resolved in ea99d5f.

supply-chain-security-expert had no findings: the empty-lock window is symlink-checked and cannot make a frozen install pass vacuously, and reading apm_modules/_local is stronger than parsing a writable source copy.

Deferred (out-of-scope follow-ups)

  • (panel) Explain why claude plugin details reports Skills (0) for the fixture, then lock the answer in with an assertion. Scope boundary: this needs an authenticated, trusted Claude session, which is exactly what the manual check covers.
  • (panel) Turn the persist-then-native-resync ordering into a shared native-adapter lifecycle hook. Scope boundary: cross-harness design under [EPIC] Native plugin installation and lifecycle across all APM targets #3094.

Regression-trap evidence (mutation-break gate)

  • test_empty_uninstall_lock_is_kept_only_when_removal_is_deferred and test_empty_uninstall_lock_is_removed_only_after_native_resync_converges: disabling deferral gave 3 failures; deleting the lock before resync gave 2 failures; the guard was restored.

Native evidence so far (agent, no trust, enable or session)

With real Claude Code 2.1.291, an isolated HOME and CLAUDE_CONFIG_DIR, and stack head 73a2550d0:

  • apm install -g registered apm-command-context@apm-claude at user scope, disabled, with readFromFolder pointing at the intact apm_modules plugin and no loose commands.
  • apm uninstall -g removed the registration and the empty lock.
  • claude plugin details reports Skills (0). A plain non-APM plugin shows the same for a manifest custom-path commands entry. Daniel's check settles whether that is a display gap or a loading gap.

Lint contract

The full CI-mirror Lint job is clean at the exact head: ruff check, ruff format, the YAML, file-length and relative_to guards, pylint R0801, auth signals, and architecture boundaries.

Tests

  • Related suites: 9346 passed. The only failures were 60 test_unix_install_ownership.py cases that flaked under -n 6 load; that file passes 376/376 alone on both this branch and main.
  • Fold re-run (uninstall, commands, Claude lifecycle, receipts, owner mutations): 2116 passed.
  • test(claude): protect native command context and lifecycle #3291: 29 passed.
  • Owner-touch gate: 7 owners detected; the blocked completion verified.

CI

All green at ea99d5fab: CI, Spec conformance, Merge Gate, and CodeQL. That took 0 CI fix iterations.

Mergeability status

PR head SHA CEO stance iters folds defers Copilot rounds CI mergeable mergeStateStatus notes
#3290 ea99d5f needs_discussion 1 2 2 1 (0 items) green MERGEABLE BLOCKED Ready for review; do not merge until Daniel's native check passes
#3291 73a2550 n/a - - - - stacked MERGEABLE - Stays draft until Daniel confirms

No merge, auto-merge, reviewer request, assignment or issue closure.


Generated by autopilot-pr-merge-worker. This comment is AI-generated and may contain errors.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@danielmeppiel
Daniel Meppiel (danielmeppiel) marked this pull request as ready for review November 12, 2026 10:40
@danielmeppiel
Daniel Meppiel (danielmeppiel) requested a review from Sergio Sisternes (sergio-sisternes-epam) as a code owner November 12, 2026 10:40
Copilot AI balanced review requested due to automatic review settings November 12, 2026 10:41
Copilot started reviewing on behalf of Daniel Meppiel (danielmeppiel) November 12, 2026 10:41
View session
Copilot AI reviewed Nov 12, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical reconciliation, migration, and persistence flaws can remove authorized Claude registrations, lose activation choices, duplicate loaded content, and mutate native state without saving recovery data.

4 open issues
  • High severity Preserve authorized Claude registrations during cross-target installs · New
  • High severity Skip native reconciliation when required lockfile persistence fails · New
  • High severity Block native migration while edited loose Claude content remains · New
  • Medium severity Skip Claude client initialization when no plugins need reconciliation · New
What changed in this PR

This PR adds intact native registration for eligible global Claude plugins, addressing missing hook resources and plugin-root context from #3191. It reuses APM's acquisition, authorization, scanning and lockfile infrastructure. Registration remains metadata-only; actual hook and command execution is still unqualified.

Changes:

  • Add Claude admission, metadata transport, ownership reconciliation and complete-source fingerprint verification.
  • Integrate native registration with installation, read-only audit and recoverable uninstall while preserving target-specific routing.
  • Add lifecycle, migration and architecture regression coverage, plus documentation of admission limits and recovery.
File Description
tests/​utils/​claude_native_protocol.py Adds a metadata-only Claude transport substitute.
tests/​unit/​test_deployment_materialization_receipts.py Tests empty-lock retention during native cleanup.
tests/​unit/​scripts/​test_architecture_runner.py Includes the Claude ownership rule.
tests/​unit/​integration/​test_mcp_config_view.py Checks read-only local-plugin MCP inspection.
tests/​unit/​install/​test_legacy_plugin_compat.py Tests normalized plugin intent preservation.
tests/​unit/​install/​test_claude_native_registration.py Covers registration, integrity, activation and recovery.
tests/​unit/​install/​test_claude_native_hooks.py Tests native routing and loose-content preservation.
tests/​unit/​install/​test_claude_native_admission.py Tests capability, selection and source-safety gates.
tests/​spec_conformance/​test_claude_cleanup_roots.py Adds retained-hook preservation cases.
tests/​integration/​test_codex_native_plugin_lifecycle.py Exercises Codex registration with both targets selected.
tests/​integration/​test_claude_native_hook_lifecycle.py Tests installed-CLI lifecycle with substituted metadata transport.
tests/​integration/​test_architecture_skill_preflight.py Updates shared deployment-plan mutation checks.
tests/​integration/​test_architecture_owner_rule_mutations.py Adds Claude ownership and integrity mutations.
tests/​integration/​test_architecture_native_plugin_audit.py Updates native audit routing mutation coverage.
src/​apm_cli/​integration/​hook_ownership.py Adds shared read-only hook-object parsing.
src/​apm_cli/​integration/​hook_integrator.py Adds dry-run hook cleanup inspection.
src/​apm_cli/​install/​target_warnings.py Receives existing executable-skip warnings.
src/​apm_cli/​install/​target_filter.py Receives hook reconciliation diagnostics.
src/​apm_cli/​install/​services.py Queues Claude plugins and checks retained hooks.
src/​apm_cli/​install/​pipeline.py Runs Claude registration after shared gates.
src/​apm_cli/​install/​phases/​claude_plugins.py Hands saved lock state to Claude reconciliation.
src/​apm_cli/​install/​legacy_plugin_compat.py Preserves normalized marketplace-plugin classification.
src/​apm_cli/​install/​drift.py Adds Claude fingerprint verification and scratch normalization.
src/​apm_cli/​install/​deployment_plan.py Shares native admission and projection decisions.
src/​apm_cli/​install/​context.py Stores admitted Claude plugin plans.
src/​apm_cli/​commands/​uninstall/​cli.py Adds Claude cleanup and deferred empty-lock removal.
src/​apm_cli/​claude_plugins/​registrar.py Owns Claude catalog, ledger and lifecycle reconciliation.
src/​apm_cli/​claude_plugins/​client.py Adds version-pinned metadata-only CLI transport.
src/​apm_cli/​claude_plugins/​admission.py Validates complete plugins and fingerprints sources.
src/​apm_cli/​claude_plugins/​__init__.py Introduces the Claude native package.
scripts/​architecture_linter/​checks/​marketplace_package_and_registration.py Enforces Claude ownership and shared routing boundaries.
packages/​apm-guide/​.apm/​skills/​apm-usage/​commands.md Documents native installation, audit and recovery.
docs/​src/​content/​docs/​reference/​package-types.md Explains intact Claude plugin eligibility.
docs/​src/​content/​docs/​reference/​cli/​uninstall.md Documents native cleanup and recovery locks.
docs/​src/​content/​docs/​reference/​cli/​install.md Documents client requirements and rollback limits.
docs/​src/​content/​docs/​producer/​author-primitives/​hooks-and-commands.md Explains native hook preservation and migration limits.
docs/​src/​content/​docs/​consumer/​installing-from-marketplaces.md Details native scope, integrity and qualification limits.
CONFORMANCE.md Updates retained-hook requirement coverage counts.
CONFORMANCE.json Records five new retained-hook conformance cases.
.apm/​architecture/​owners/​marketplace-plugins.json Registers the Claude native lifecycle owner.

Review effort: Balanced

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/apm_cli/claude_plugins/registrar.py
Comment on lines +436 to +437
if plan is None:
continue
Comment thread src/apm_cli/commands/uninstall/cli.py
Comment on lines +130 to +133
empty = persist and bool(
_persist_uninstall_lockfile(lockfile, lockfile_path, logger, integration_cleanup)
)
_resync_native_registration_after_uninstall(
Comment thread src/apm_cli/install/phases/claude_plugins.py
"""Use the same reconciliation owner as removal, with scanned new plans."""
if ctx.apm_modules_dir is None:
return
resync_claude_plugins(
Comment thread src/apm_cli/claude_plugins/registrar.py
_check_bundle_fingerprint(plugin.source_root, plugin.bundle_hash)
desired[plugin_id] = entry

client = ClaudePluginCLI()
@danielmeppiel Daniel Meppiel (danielmeppiel) mentioned this pull request Nov 12, 2026
[FEATURE] Anchor user-scope hook commands to $HOME on POSIX targets so ~/.claude/settings.json stays portable across machines #2821
Open

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments
@sergio-sisternes-epam Sergio Sisternes (sergio-sisternes-epam) Awaiting requested review from sergio-sisternes-epam sergio-sisternes-epam is a code owner

At least 0 approving reviews are required to merge this pull request.

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@danielmeppiel Daniel Meppiel (danielmeppiel)

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@danielmeppiel
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.