Skip to content

fix(audit): ignore hook sidecar object-key order - #3155

Merged
Daniel Meppiel (danielmeppiel) merged 11 commits into
microsoft:mainfrom
Pybsama:codex/fix-claude-hook-drift-key-order
Oct 16, 2026
Merged

Daniel Meppiel (danielmeppiel) merged 11 commits into
microsoft:mainfrom
Pybsama:codex/fix-claude-hook-drift-key-order

Conversation

@Pybsama

@Pybsama sama Pyb (Pybsama) commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Description

A clean install can fail apm audit --ci when a consumer already has Claude hook events: the live merge and the empty scratch replay write ownership sidecar keys in different orders. Compare registered hook sidecars as UTF-8 JSON, preserving every field and list order while ignoring object-key order and formatting. Invalid encoding, malformed JSON, duplicate keys and non-JSON constants (NaN, Infinity, -Infinity) still produce drift findings. The existing ownership guard protects this comparison and its drift call sites; bundled CLI guidance matches the public documentation.

Shared native hook configurations continue to compare only APM-owned entries. Lockfile hashing and ownership decisions are unchanged.

Issue and approved scope

Fixes #3062.

Human scope approval: #3062 (comment)

This covers the approved false-positive repair and preserves meaningful drift detection.

Type of change

  • Bug fix
  • Documentation

Testing

  • Tested locally
  • Added regression tests

The hermetic install/install/audit regression fails against the original source and passes with this change. It checks stable repeated installation, preservation of user hooks and read-only audit. Unit cases cover key reordering, changed commands/value types, entry removal, added events, execution order, duplicate keys, malformed JSON and unsupported UTF-16/32 encodings.

uv run pytest tests/unit/install/test_drift.py tests/integration/test_drift_check.py tests/integration/test_hook_sidecar_drift_e2e.py tests/unit/integration/test_hook_integrator.py tests/unit/integration/test_hook_integrator_defect_regression.py tests/unit/install/test_drift_phase3.py tests/integration/test_drift_check_e2e.py -q: 364 passed. Four architecture mutation regressions also pass; they cover missing comparison authority, duplicate ownership, and bypassed drift call sites.

The six CI test-quality/architecture-ratchet modules also pass locally: 91 passed. Full-source Ruff lint/format and pylint duplication checks, YAML I/O/file-length/portable-path guards, auth and architecture boundary checks, and git diff --check pass. The full functional suite and Windows runtime were not run locally; these are local checks, not a claim that GitHub CI has run.

Spec conformance (OpenAPM v0.1)

No normative requirement changes: sidecars are outside the deployed-file hash maps governed by req-lk-012/017, and this change does not alter the ownership/reconciliation obligations in req-lk-021.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Nonstandard JSON constants remain accepted, and required architecture and bundled-guide updates are missing.

Review effort: Balanced
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Fixes false drift findings caused by JSON object-key ordering in hook ownership sidecars.

Changes:

  • Canonicalizes sidecar JSON while preserving values and list order.
  • Adds unit and end-to-end regression coverage.
  • Updates audit documentation.
File Description
src/​apm_cli/​integration/​hook_ownership.py Adds sidecar canonicalization.
src/​apm_cli/​install/​drift.py Uses canonical comparison for sidecars.
src/​apm_cli/​install/​manifest_reconcile.py Updates reconciliation documentation.
tests/​unit/​install/​test_drift.py Covers sidecar comparison cases.
tests/​integration/​test_hook_sidecar_drift_e2e.py Tests install and audit lifecycle.
docs/​src/​content/​docs/​reference/​cli/​audit.md Documents JSON comparison behavior.
docs/​src/​content/​docs/​reference/​baseline-checks.md Updates drift-check semantics.
docs/​src/​content/​docs/​enterprise/​drift-detection.md Updates enterprise guidance.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/apm_cli/integration/hook_ownership.py
Comment thread src/apm_cli/integration/hook_ownership.py Outdated
Comment thread docs/src/content/docs/reference/cli/audit.md Outdated
sama Pyb (Pybsama) and others added 10 commits October 3, 2026 13:55
Resume the retained ee08bb5 merge without discarding contributor work. Consolidate the duplicate Fixed heading identified by the documentation panel.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
Preserve marketplace, unmatched-skill and SSH changes from main. Resolve only the overlapping release-note insertion, retaining both entries.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
Address the retained architecture, performance and DevX panel nits: annotate the rejecting callback, reuse the linter scan inventory and keep the three public audit guides aligned with bundled constant-rejection guidance.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
Preserve canonical user-scope cleanup and containment coverage while retaining the bounded sidecar comparison repair.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
Preserve current docs and dashboard dependency updates before exact-head validation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
Move the unchanged drift logger to its existing rendering module to retain the install-engine LOC budget without changing output or import contracts.

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

Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f79e464c-180e-4be3-9056-0773aa679a1a
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

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

Copy link
Copy Markdown
Collaborator

APM review advisory: ship_now

Hook-sidecar JSON key order no longer creates false drift; meaningful changes and invalid inputs remain detectable.

cc sama Pyb (@Pybsama) Sergio Sisternes (@sergio-sisternes-epam) -- the final advisory is ready for your review.

The original six-persona panel was reused, not repeated. Its four follow-ups are folded: one Unreleased Fixed section, the NoReturn annotation, consistent non-JSON-constant guidance, and a single source-path scan in the architecture guard. Bounded architecture, documentation, and test-coverage deltas have no remaining findings.

The real CI repair adds executable coverage of existing req-pl-014: reordered sidecars audit clean, while changed commands remain reported and obey fail_on_drift. It also moves the unchanged logger into the existing rendering module, preserving its import and stderr behavior without raising the LOC budget. No normative requirement, integrity exemption, or lockfile-hash change was introduced.

Verified at 67337f7b64f85e8a25218fa40888cdeead00c52e:

  • 392 local tests passed, with two pre-existing conformance skips; every current lint check passed.
  • Deliberately removing canonicalization caused five failures; discarding content caused sixteen; disabling the ownership rule caused four. All mutations were restored and all 23 regression cases passed.
  • The final canonical-owner verifier passed with executed consumer evidence for both detected owners.
  • CI, conformance, CodeQL, docs, NOTICE, and combined checks all passed. Both CodeQL analyses were actually uploaded.

Local tests used main bd67298121. GitHub validated merge b0e292fea2, combining this head with newer main 6333b56a3c; its tree matches the clean compatibility preview. Commands, ownership markers, field values, and list/execution order remain significant; strict JSON rejection preserves fail-closed comparison rather than replacing integrity checks.

No outstanding panel findings or deferred implementation remain. The maintainer's renewed scope record is unchanged. This is technical advice only: no merge was performed, and existing review requests and repository rules are unchanged.


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

@danielmeppiel
Daniel Meppiel (danielmeppiel) merged commit b71cb47 into microsoft:main Oct 16, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

apm audit --ci: false 'modified' drift on .claude/apm-hooks.json when the consumer's settings.json already has hook events (key order)

3 participants