Skip to content

Report hosted-mode adoption and self-update in telemetry - #1360

Merged
Mikola Lysenko (mikolalysenko) merged 47 commits into
mainfrom
fix/telemetry-depscan-compat
Oct 10, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 47 commits into
mainfrom
fix/telemetry-depscan-compat

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This PR audits socket-patch telemetry against depscan's v0 /orgs/:slug/telemetry handler and the patches API proxy, and fixes the gaps.

  • Wire format was already compatible. All 17 existing event types were in depscan's patch event map. The proxy forwards the body unchanged. Events carry no event_kind, so depscan stores them as required events even without org opt-in.
  • Hosted-mode installs were invisible. v5 made --mode hosted the default for scan, but the hosted path sent no outcome event. A default scan therefore recorded only patch_scanned, never patch_applied, and adoption dropped out of the patch-adoption dashboard. scan/get --mode hosted now send patch_applied (or patch_apply_failed) with mode: "hosted", patches_count and files_count. The success event is sent before the result prints, so a closed stdout can't drop it. Agent-mode apply events gain mode: "agent".
  • Self-update had no telemetry. socket-patch --update now sends cli_updated (from_version, to_version, channel, pinned, forced) or cli_update_failed (the envelope's error_code plus the message). The new types need SocketDev/depscan#27684. Without it they're stored as external.
  • patch_scanned.ecosystems now lists the ecosystems the crawl found. It previously echoed the --ecosystems filter, which is empty on every default run.
  • Mode adoption by client version: patch_scanned gains mode and project_modes. mode is what the run was asked for (hosted / vendored / agent, or report with none). project_modes is what the project is already wired for (hosted lockfile pins, a vendor ledger, an agent manifest). Every event already carries context.version, so this gives mode usage per client version from the one event every scan sends.
  • Contract test: a core test pins depscan's accepted event types and the body shape its handler extracts.
  • Docs: CLI_CONTRACT.md gains a table of which command sends which event.

Test plan

  • New core tests: backend event-type contract, wire shape, each new tracker against wiremock
  • New e2e tests: requested/project modes on scan and re-scan, hosted scan success/failure, get --mode hosted, self-update success/failure/--offline
  • Regression: CLI lib + update/get/scan/cli/hosted/redirect/self-update suites, 1,805 tests green locally
  • cargo clippy --locked --workspace --all-features -- -D warnings, cargo fmt --check

Merge depscan#27684 first or alongside. A depscan submodule bump afterwards lets 82_socket-patch-telemetry-coverage.ts exercise these paths end to end.

🤖 Generated with Claude Code


Note

Low Risk
Changes are limited to optional telemetry payloads and timing; patch/redirect behavior is unchanged aside from when events fire.

Overview
Hosted-mode scan/get now emit adoption telemetry so default v5 scans show up on patch-adoption dashboards: non-empty hosted redirects send patch_applied with mode: "hosted", patches_count, and files_count (or patch_apply_failed on early exit), with context.command set to scan or get. Agent apply paths tag existing apply events with mode: "agent".

socket-patch --update reports cli_updated (versions, install channel, pin/force flags) or cli_update_failed (envelope error_code plus message), sent before human/JSON output like other commands.

patch_scanned metadata now lists ecosystems discovered from crawled PURLs via scanned_ecosystems, not the often-empty --ecosystems filter.

Contract and tests: CLI_CONTRACT.md documents per-command events; socket-patch-core adds trackers, a depscan event-type allowlist test, and wire-shape checks; new e2e coverage for hosted scan/get and self-update (including --offline sending nothing).

Reviewed by Cursor Bugbot for commit ea70e1b. Configure here.

, #1066)

GC was reported four ways. repair and remove buried the sweep in
artifact-level event details with no byte count, while rollback and
scan --prune printed a hand-built `gc` object. The contract documented
summary.bytesFreed, summary.bytesDownloaded and events[].bytes, but no
command emitted any of them, so its GC jq recipe returned null.

- json_envelope::GcReport {removedBlobs, removedDiffArchives,
  removedPackageArchives, bytesFreed} is built from the three sweep
  passes and serialized identically everywhere: the envelope's new
  top-level `gc` (repair, remove), rollback's `gc` and scan's `gc`. The
  hand-written json! blocks are gone.
- summary.bytesFreed is always present and mirrors gc.bytesFreed.
  events[].bytes is set on the GC carrier event and on --update's
  downloaded event. summary.bytesDownloaded is dropped from the contract.
- repair's GC carrier event no longer bumps summary.removed/verified,
  matching remove: summary counters count patch entries, and the sweep
  totals live in `gc`.
- remove's human output now names the diff/package archives it sweeps.
- rollback --json: rolledBack and failed now span the agent, vendored
  and hosted legs (#1066). A run where something failed and nothing was
  rolled back, already original or not installed now reports
  status "error" with error.code rollback_failed instead of
  partial_failure. Exit codes are unchanged.
- CLI_CONTRACT.md: the envelope and PatchEvent schemas, the PatchAction
  "Emitted by" column, the per-command action matrix and the GC jq
  recipe now match the emitters. New unit tests pin the documented
  summary/gc/PatchEvent key sets against what json_envelope serializes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The --dry-run preview of scan --prune/--sync used its own vocabulary
(prunableManifestEntries, orphanBlobs, orphanDiffArchives,
orphanPackageArchives, revertableVendoredEntries, vendorOrphanDirs,
bytesReclaimable). It now prints the same keys as the wet pass and every
other GC-running command, counting what the pass would remove, and leaves
out only the keys a real pass alone can fill (keptVendoredEntries,
failedVendoredEntries, skipped, warnings). v5.0 MAJOR.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Envelope::extra (flattened) carries a command's own payload keys
  beside the shared ones; set_extra refuses a shared key.
- Status gains notInstalled, noMatch, noPackages and selectionRequired
  (get's outcomes) so no command needs a snake_case status.
- PatchAction gains rolledBack; summary.rebuilt and summary.rolledBack
  are always present.
- manifest_load_error is the one mapping from a manifest load failure to
  manifest_invalid / manifest_unreadable (#931); list and remove use it,
  and remove reports a manifest that vanished mid-run as
  manifest_not_found instead of manifest_invalid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every rollback outcome is now a PatchEvent: agent restores are rolledBack
(verified on a dry run, installed copy in details.path), already-original
and not-installed entries are skipped with already_original /
package_not_installed, failures are failed with the blocking file's code.
Vendored and hosted legs carry details.mode; drift-keeps are failed
vendor_revert_kept (they still exit 1). Manifest entries the run drops are
removed (verified on a dry run) with details.manifest. GC goes through
set_gc; a requested GC that could not run adds the gc_skipped warning.
Every error path prints a full envelope; manifest load failures use
manifest_load_error.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#931)

apply, apply --check, repair, vendor, vendor --check and vex now report an
unparseable manifest as manifest_invalid and an unreadable one as
manifest_unreadable through json_envelope::manifest_load_error, like list
and remove. Gone: apply_failed / repair_failed for a manifest load
failure, and vendor's undocumented invalid_manifest. vex keeps exit 2.
apply's run_locked reports a manifest that vanished mid-run as
manifest_not_found. Exit codes are unchanged.

remove's GC carrier now matches repair's (details.count + details.checked,
bytes); the per-kind totals are only in gc. The in-place rollback leg is
reported as rolledBack events (summary.rolledBack) instead of the carrier's
details.rolledBack. Sweep failures reach --json as cleanup_failed
warnings. Vendored- and hosted-leg events of remove and repair carry
details.mode; repair's download carrier key is now details.downloadMode.

Sidecar file actions and severities serialize with the envelope's
camelCase enum convention (wire-identical for today's one-word values).

Adds a regression matrix test over list, remove, apply, apply --check,
repair, vendor, vendor --check and vex.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
v5 made `--mode hosted` the default for `scan`, but the hosted path
sent no outcome event, so a default scan recorded only
`patch_scanned` and patch adoption vanished from the backend's
patch_applied counts. `scan`/`get --mode hosted` now report
`patch_applied` (or `patch_apply_failed`) with `mode: "hosted"`,
`patches_count` and `files_count`, sent before the result prints.
Agent-mode apply events gain `mode: "agent"`.

`socket-patch --update` now reports `cli_updated` (from/to version,
channel, pinned, forced) and `cli_update_failed` (with the envelope's
error code). depscan needs these two types in its patch event map;
see the companion depscan change.

`patch_scanned.ecosystems` now lists the ecosystems the crawl found
rather than echoing the `--ecosystems` filter, which was empty on
every default run.

A core test pins the event types depscan's discriminator map accepts
and the body shape its v0 handler extracts (no `event_kind`, so
events stay required and are stored without org opt-in). The CLI
contract gains a telemetry event table.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adds tests/common/rollback_json.rs, per-leg views projected from events,
and moves the rollback-centric suites onto summary/events.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ea70e1b. Configure here.

Comment thread crates/socket-patch-cli/src/commands/scan/hosted.rs
Covers the mixed suites (apply multicopy, dispatch, global scope, json
error shape, hosted/vendored takeovers) and the ignored e2e suites, which
were fixed by reading.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CLI_CONTRACT.md: manifest_invalid / manifest_unreadable now list every
command that loads the manifest (v5.0, MAJOR, #931; vex keeps exit 2);
the top-level error table gains the codes apply, remove, vendor, vex and
--update already emitted; the remove/repair matrix rows, the rolledBack
action row and new notes describe the shared GC carrier (details.count +
checked), details.mode on vendored/hosted-leg events, repair's
details.downloadMode, and the sidecars[] value-tag casing.

apply --check prints a noManifest envelope when the manifest vanishes
between the existence probe and the read, instead of printing nothing.
Tests pin details.mode on remove's hosted/vendored legs and repair's
vendored phase.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
All packages refused and nothing rolled back is a failed run since #1066.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The rollback contract's JSON section now maps each outcome to its event,
the action matrix and migration status list rollback as an envelope
command, and the errorCode / EnvelopeError tables carry its codes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
scan and get now print one serialized Envelope per run (command,
status from the Status enum, dryRun, events, summary, warnings, gc,
vex), built by one emitter each (scan::emit_scan, get::emit):

- The agent download engine records per-patch events into the caller's
  envelope (downloaded / updated + oldUuid with the patch metadata in
  details, skipped already_in_manifest, failed with download_failed /
  patch_no_applicable_files / blob_write_failed or the refusal code),
  then applied / failed events for the nested apply; it never prints,
  so scan --mode agent --json can no longer put two JSON documents on
  stdout when the lock is held or the manifest is unreadable.
- Hosted runs record applied (verified on --dry-run) / skipped events
  tagged details.mode hosted; redirect shrinks to {mode, rewrittenFiles}
  and its warnings move to the top level.
- Vendored runs merge the vendor engine's events, warnings and sidecars
  into the outer envelope (details.mode vendored) instead of nesting a
  vendor envelope; the dry-run preview becomes verified / skipped events.
- scan --prune records pruned manifest entries as removed events
  (details.manifest), reverted vendored entries as removed, drift-kept
  and failed reverts as skipped, the sweep as the envelope's gc, and a
  pass that could not take the lock as a gc_skipped warning.
- get's statuses become notFound / noPackages / noMatch / notInstalled /
  paidRequired / selectionRequired; selection_required options use
  publishedAt; every error prints a full envelope.
- Exit parity (#1062): one fetch_details decision for both outputs, no
  human-only fetched == 0 failure, hosted --json uses the policy-gated
  prune, and the human vendored dry run previews the --prune GC.
- A manifest that exists but cannot be loaded fails agent-mode scan with
  manifest_invalid / manifest_unreadable and is a warning elsewhere.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CLI_CONTRACT.md: scan and get join the envelope (migration status,
action matrix, PatchAction rows, error codes, a new "scan and get JSON"
section replacing the patches[] entry shape, jq recipes), and the scan
mode / get paragraphs describe events, the redirect payload and top-level
warnings instead of the nested blocks.

Tests: shared envelope invariants in tests/common/envelope.rs, a legacy
redirect rebuild for the in-memory engine parity harness, scan envelope
tests (agent events, dry run, lock held prints one document, manifest
load errors) and the #1062 human/JSON parity tests, get envelope tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every test that read the legacy scan/get JSON (top-level counters,
patches[], apply / download / vendor / redirect blocks, nested and string
warnings, snake_case statuses and actions, gc sub-keys) now reads the
envelope: events (details.mode for the hosted and vendored legs), summary,
top-level warnings, redirect.rewrittenFiles and the scan payload keys.
The in-memory hosted engine parity tests compare the engine's redirect
block against one rebuilt from the disk run's envelope. Env-gated e2e
files were updated by reading.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every command now prints the envelope, so the legacy error helpers
(legacy_error, set_error, is_legacy_shape, …) are deleted and every usage
error is a full envelope.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`patch_scanned` now carries `mode`, the mode the run was asked for
(`hosted` / `vendored` / `agent`, or `report` with none), and
`project_modes`, the modes the project is already wired for: hosted
lockfile pins, a vendor ledger, an agent manifest (several during a
migration). With the client version every event already carries in
`context.version`, this gives per-version mode adoption from the one
event every scan sends, including runs that change nothing.

Fields on the existing event: always stored (no event_kind), works
for anonymous proxy traffic, no depscan change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[final reviewer] Not enqueuing. Tanmay Singla (@Tanmay182003), two non-merge commits landed after your approval at ea70e1b2:

  • 7a00157a Report requested and wired patch modes in patch_scanned (commands/scan/mod.rs, telemetry_e2e.rs, redirect/upstream/mod.rs, CLI_CONTRACT.md, +162/-10)
  • 7f842ce0 Drop an unrelated rustfmt change to upstream/mod.rs (+1/-4)

There is also 1 open review thread. Please take another look at 7a00157a in particular, since it adds new telemetry fields.


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
The shared bun.lockb rollback helper expected status "error" for every
caller, so the hosted -> vendored -> hosted takeover leg went red: there
a manifest record makes the agent leg report the copy already original,
and the run is correctly a partial_failure. A branch rewrite had dropped
the earlier fix for this. Each caller now states which outcome it
expects, so the takeover leg checks partial_failure and the hosted-only
alias/transitive shapes keep checking rollback_failed.

Assisted-by: Claude Code:claude-opus-5-5
Resolve against main's removal of the diff download path (#1049) and
the restore-blob GC fix (#1316): repair drops the created-file blob
pass and keeps the GcReport carrier; remove keeps the archive noun
loop; the contract keeps "update" and drops the removed paidRequired
status; the envelope contract test uses AppliedVia::Blob.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
main's new test read gc.prunableManifestEntries, which this branch
renamed to prunedManifestEntries for the dry-run preview.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in main through #1277 via #1273. Resolutions:
- get keeps the envelope's paidRequired status and drops main's legacy
  {"status": "paid_required"} emitter; contract_paid_required.rs now pins
  the envelope row instead of the legacy one.
- repair: main removed the diff download path, so the created-file blob
  pass is gone; the download event keeps details.downloadMode, now
  always "file".
- scan: the envelope arms read main's lockfile_only_count; main's
  hoisted release-variant narrowing replaces the hosted-only copy in get.
- CLI_CONTRACT.md: three-way merged per paragraph; main's new hosted
  warning rows point at the top-level warnings[] like their neighbours.
- tests: main's new tests (cargo takeover refusal, #1127 human prune,
  bun.lockb already-original rollback) read the envelope shapes.
- json_envelope contract tests normalize CRLF so they pass on a Windows
  checkout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The envelope retired scan's legacy counters and nested blocks, but the
ignored e2e suites, the Python compatibility harnesses and the scan
benchmark still read them, so every compat workflow failed.

- e2e (hosted production, gem, vlt, bun.lockb, pypi/yarn hosted): hosted
  pins are the details.mode "hosted" applied/verified events, skips the
  hosted skipped events, warnings the top-level warnings[] (omitted when
  empty), prune reverts the vendor_reverted events, hosted rollback
  restores rolledBack events.
- scripts/backtest-{bun,uv,vlt,pdm,pipenv,poetry}.py: per-leg event
  counts replace redirect.redirected / vendor.summary.applied /
  apply.applied, and codes come from error.code, event errorCodes and
  warnings[]; the harness unit tests use envelope fixtures.
- socket-patch-bench: validation accepts both shapes, since the base and
  head binaries straddle the change (packagesWithPatches and
  totalPatches derive from packages[], redirected from the hosted
  events).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
run_redirect_selected sent patch_apply_failed only after the inner run
returned, by which point every --json failure path had already printed
its error envelope. A consumer that closed stdout on that first write
killed the process (SIGPIPE) before the event went out. The failure
paths now build the envelope into HostedTelemetry and the wrapper prints
it after sending the event, matching the success path, which already
sends before printing. Adds a closed-stdout e2e test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
….lockb e2e

- json_envelope's contract tests read CLI_CONTRACT.md through one
  LF-normalized copy, so a Windows checkout (CRLF) no longer misses the
  ```jsonc fence (review thread on #1273; full-scope test windows).
- e2e_bun_lockb's shared-bundled case also has an agent copy that fails
  (hash_mismatch on a bundled copy the patch never touched); with #1066's
  all-leg counter, `failed` is the hosted refusal plus those agent failures.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Takes #1273's LF-normalized contract_doc(); the bun.lockb shared-bundled
rollback counts agent failed events (no details.mode) on top of the
refused hosted pin.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The vendor engine marks a hard error and still returns Ok for an
unreadable vendor ledger, a refused group commit and
vendor_commit_failed. merge_vendor_envelope dropped venv.error, so a
corrupt .socket/vendor/state.json under scan/get --mode vendored --json
printed a bare partialFailure with no code. The merge now marks the
outer envelope with the engine's {code, message}; a caller aborting
with its own error still overrides it. Unit tests pin both arms.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 10, 2026
Resolve remove.rs imports: keep main's KeepCause and this branch's GcReport.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in main's latest via #1273. Conflicts:
- CLI_CONTRACT.md: keep the envelope wording and port main's additions
  (cargo_build_cache_stale, cargo_cache_patch_kept, the Cargo shared-cache
  exemption in GC and rollback, redirect_cargo_dep_overridden,
  vendor_pypi_reinstall_required, vendor_revert_residual_reference, the
  pnpm keyless-yaml restore) onto it; GC warnings are top-level
  warnings[], a kept entry gets no preview event, and rollback's residual
  keep is its failed vendor_revert_kept event.
- rollback.rs tests: keep both the envelope tests and the PyPI reinstall
  note test.

Port main's new tests to the envelope: e2e_cargo reads pruned manifest
entries from details.manifest events and cargo_cache_patch_kept from the
top-level warnings; in_process_redirect and mode_migration_pypi count
hosted pins from events and read redirect_vendored_revert_failed from
the top-level warnings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
main's #1278 e2e (sync_keeps_entry_whose_shared_cache_copy_is_still_patched)
reads the preview's prunableManifestEntries, which the one GC shape
renamed to prunedManifestEntries; the contract text it brought gets the
same rename.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Keep the envelope ports of e2e_cargo and the Cargo GC contract text
(pruned entries are details.manifest events, so the preview key rename
on #1273 does not apply here).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#1305's sync_keeps_entry_whose_shared_cache_copy_is_still_patched
asserted the scan --sync --dry-run preview via gc.prunableManifestEntries,
a key #1273 retires: under the one GC shape a dry run reports would-be
prunes as gc.prunedManifestEntries. The keep logic itself merged intact
(preview and wet pass both keep the still-patched itoa entry, and the wet
pass reports cargo_cache_patch_kept in gc.warnings[] with the purl and the
rollback remedy), so only the test read the wrong key. Assert the same
ryu-only list under the new key.

CLI_CONTRACT.md's scan --prune paragraph still named the retired preview
keys (prunableManifestEntries, revertableVendoredEntries,
vendorOrphanDirs); point it at the unified keys and note that the
preview, like every warnings[] entry, carries no cargo_cache_patch_kept.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	crates/socket-patch-cli/CLI_CONTRACT.md
Keep the envelope wording for the Cargo shared-cache GC keep (no event
and no warning in the preview) and take #1273's vendor_artifact_gitignored
NuGet/JVM contract updates with the envelope's top-level warnings[].
e2e_cargo keeps the events-based prune read with #1273's message.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#1273 landed as squash e3eaa0c, whose tree is fix/gc-report-json-1257
(ff9704a, already merged here) plus #1342. Conflicts take this branch's
side throughout (the squash adds nothing beyond ff9704a); #1342's
nuget_feed.rs merges cleanly and its CLI_CONTRACT.md nuget drift note is
ported.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Ports main's new output onto the envelope:
- hosted scan: NuGet stale-global-package (#352) and Go consumer-sync
  (#343) warnings join the top-level warnings[] as RunWarnings.
- get / agent download: vendored-uuid drift check reads the manifest
  project's ledger (project_root, #745) with the envelope's recorded pairs.
- e2e_nuget_dotnet_build: keeps summary.applied for the hosted pin and
  adds main's stale-global-package assertions.
- CLI_CONTRACT.md: main's NuGet mapping set-aside (#462/#354), the
  stale-global-package row (envelope wording), and the --manifest-path
  root note (#745) merged into the envelope text.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Resolve hosted.rs: keep #1369's Envelope-based error path and carry
#1360's deferred --json error envelope (now an Envelope) so hosted
failure telemetry still goes out before the error prints.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
v5.0's single JSON envelope drops redirect.redirected; each confirmed
hosted pin is now an applied event tagged details.mode: "hosted".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Picks up #1369 (squashed) and #1343. scan/hosted.rs and scan/mod.rs on
main are identical to the v5/json-envelope-unify tip already merged, so
both conflicts resolve to the existing resolution.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merged via the queue into main with commit 468879e Oct 10, 2026
52 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the fix/telemetry-depscan-compat branch October 10, 2026 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants