Add inline script environment lifecycle telemetry (PEP 723 PR 15/16) - #1723
Merged
Stella Huang (StellaHuang95) merged 4 commits intoAug 19, 2026
Merged
Conversation
Contributor
|
🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR. |
Rich Chiodo (rchiodo)
approved these changes
Aug 18, 2026
Rich Chiodo (rchiodo)
left a comment
Contributor
There was a problem hiding this comment.
Approved via Review Center.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3cb82ae9-7424-40a4-9156-8c54ac6e0895
Cover detailed uv outcomes and normalized dependency counts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6b12d843-8011-4bfc-9ba9-f75761eadee2
Keep telemetry-only helpers scoped to their consuming test suite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6b12d843-8011-4bfc-9ba9-f75761eadee2
Report reuse dependency counts and preserve accurate final failure outcomes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6b12d843-8011-4bfc-9ba9-f75761eadee2
Stella Huang (StellaHuang95)
force-pushed
the
pep723-pr15-telemetry-v2
branch
from
August 19, 2026 16:55
80c6ae5 to
ad46274
Compare
Eleanor Boyd (eleanorjboyd)
approved these changes
Aug 19, 2026
Stella Huang (StellaHuang95)
merged commit Aug 19, 2026
655b075
into
microsoft:main
43 of 44 checks passed
Stella Huang (StellaHuang95)
added a commit
that referenced
this pull request
Sep 1, 2026
> Part of #1602 (PEP 723 inline script env support). Design doc: #1601. ### Roadmap context This is **PR 14 of 16** in the PEP 723 inline-script roadmap. PR 13 added explicit, user-confirmed cache cleanup; this PR adds the separate best-effort TTL path. | Phase 5: Lifecycle and polish | PR | Status | |---|---|---| | | PR 7: persistence (`get` / `set` + Memento) | merged (#1697) | | | PR 13: Clear Script Environment Cache | merged (#1724) | | | **PR 14: opportunistic 14-day TTL eviction** | **this PR** | | | PR 15: lifecycle telemetry | merged (#1723) | | | PR 16: status-bar decision | resolved; no code PR | ### Why this PR Inline-script environments are dependency/interpreter-keyed and intentionally rebuilt instead of synchronized in place. Without lifecycle cleanup, old cache keys accumulate whenever dependencies or the selected Python change. The design calls for a pipx-style 14-day TTL in addition to the explicit clear command. Because TTL cleanup is silent, it must be more conservative than user-confirmed cleanup and must never prevent the requested environment from being created. ### What this PR does - Attempts one TTL sweep per `InlineScriptEnvManager` session. - Runs the sweep before the first environment creation/reuse reaches the cache. - Reads only valid `.meta.json` sidecars and selects entries whose `lastUsedAt` is strictly older than 14 days. - Reuses PR 13's physical-root, normal-directory, direct-child, and entry-lock safety checks. - Re-reads `lastUsedAt` under the entry lock before deletion. - Preserves held, retained, malformed, redirected, unavailable, or failed-to-delete entries. - Treats all TTL failures as best-effort warnings and continues the triggering creation. - Invalidates persisted and warm script associations only for entries confirmed deleted or definitively removed by another host. - Removes evicted environments from the discovered collection and emits the existing environment-change events. - Prevents a concurrent discovery refresh from publishing a stale snapshot after eviction. ### Eviction semantics | State | Behavior | |---|---| | `lastUsedAt` older than 14 days | Lock, revalidate, and delete | | Age exactly 14 days | Keep | | Recent or future timestamp | Keep | | Missing, invalid, unsupported, or unreadable sidecar | Keep | | Timestamp becomes fresh before lock acquisition | Keep | | Entry is actively locked | Keep | | Entry has a retained cancellation lock | Keep; only explicit cleanup may reclaim it | | Entry deletion fails | Keep and continue creation | | Another host already deleted the entry | Confirm with `lstat`, then invalidate local associations | | Association persistence fails after deletion | Keep in-memory state consistent, log, and continue creation | | Refresh started before deletion | Reject its stale collection snapshot | | Refresh starts during maintenance | Wait, then scan the post-eviction cache | ### Concurrency and safety - The once-per-session latch is set synchronously, so concurrent creates share one sweep. - The sweep uses the existing cache-maintenance then selection-queue ordering. - The active-create counter is incremented before the sweep, preserving PR 13's clear-vs-create behavior. - Each deletion is protected by the existing cross-host cache-entry lock. - Physical root and entry containment are revalidated after lock acquisition. - A cache mutation revision prevents stale discovery publication without waiting on, or deadlocking with, a refresh already blocked by maintenance. - Only `ENOENT` counts as confirmed cross-host deletion; permission and transient access errors preserve associations. ### Performance - The cache is scanned once per extension-host session, not on every lookup. - Entries are inspected and deleted sequentially to avoid I/O spikes. - Activation remains unchanged and is not blocked by TTL work. - Environments with missing or uncertain metadata are not repeatedly modified. ### User impact The feature remains behind `python-envs.inlineScripts.enabled`. Users without inline-script environments see no behavior change. Existing environments are retained unless a valid sidecar proves they have not been successfully reused for more than 14 days. ### Tests - `npm run compile-tests` - `npm run compile` - `npm run lint` - Complete unit suite: **1,928 passing**, 6 pending Focused coverage includes: - strict 14-day cutoff; - once-per-session and failed-sweep behavior; - under-lock freshness revalidation; - held and retained lock preservation; - deletion and persistence failure isolation; - cross-host deletion confirmation; - association and discovered-collection invalidation; - refresh-versus-eviction publication races; - unchanged explicit clear-cache behavior. ### Scope and follow-up This PR does not add telemetry, activation-time cleanup, a cache-root lock, project-setting cleanup, UX, or retry loops. Explicit clear-cache behavior remains unchanged. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Roadmap context
This is PR 15 of 16 in the PEP 723 inline-script roadmap. It adds the remaining lifecycle telemetry for the internal manager without changing routing, creation, or cache policy.
Why this PR
The manager can create, reuse, and persist inline-script environments, including consent-gated uv/Python fallback, but those lifecycle outcomes are not observable as a coherent feature funnel.
This PR adds low-cardinality telemetry that answers:
The instrumentation is deliberately attached to the underlying coalesced operation rather than every caller, and it excludes script/package/interpreter content.
What this PR does
Adds three typed lifecycle events
inlineScript.envCreatedinlineScript.envReuseHitinlineScript.envErrorThe telemetry constants and GDPR declarations use typed event/property mappings so call sites cannot send undeclared fields.
Reports verified creation only
envCreatedonly after environment creation succeeds, ownership/version validation passes, and.meta.jsonis persisted.Reports validated cache reuse only
envReuseHitonly after sidecar, interpreter, ownership, and compatibility checks complete successfully.lastUsedAtbehavior.Classifies lifecycle failures without leaking details
envErroruses stable low-cardinality categories for outcomes such as:Errors remain logged through the existing paths; telemetry sends no exception text.
Preserves uv consent and compatibility behavior
available,declined,failed, andinstalledoutcomes.Keeps event emission coalesced and deterministic
create()calls and pre-validation exits do not emit success-shaped lifecycle events.Event payloads and privacy
inlineScript.envCreatedinlineScript.envReuseHitinlineScript.envErrorThe events send no:
Script-controlled metadata therefore cannot create unbounded telemetry dimensions.
Lifecycle examples
Tests
Coverage includes:
Validation on the rebased branch:
npm run compile-testsnpm run compilenpm run lintThe full Windows unit run reaches 1612 passing and 5 pending; the existing concurrent
writeMetaJsonrename test can still intermittently fail withEPERMon Windows. That writer is unchanged by this PR and the same failure is reproducible onmain.Performance
User impact
No default-path user impact. The inline manager remains behind the undeclared, default-off
python-envs.inlineScripts.enabledflag.When the internal flag is manually enabled, prompts, environment creation/reuse, cancellation, error propagation, and cache behavior remain unchanged. This PR only records privacy-safe lifecycle outcomes.
Scope and follow-up
This PR intentionally does not implement:
The telemetry is ready for those later entry points to consume once the feature is intentionally exposed.