Skip to content

Align context service resolution - #4272

Merged
thomhurst merged 2 commits into
mainfrom
issue-4229-services-context
Aug 29, 2026
Merged

Align context service resolution#4272
thomhurst merged 2 commits into
mainfrom
issue-4229-services-context

Conversation

@thomhurst

@thomhurst thomhurst commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Closes #4229.

Summary

  • rename IServicesContext.Get<T>() to GetRequiredService<T>()
  • rename TryGet<T>() to nullable GetService<T>()
  • remove duplicate IPipelineContext service extensions
  • update tool accessors, generator output, docs, tests, and PublicAPI baselines

Validation

  • core Release build: 0 warnings, 0 errors
  • OptionsGenerator Release build: 0 warnings, 0 errors
  • Git integration Release build: 0 warnings, 0 errors
  • focused core, Git, and OptionsGenerator tests passed

Summary by CodeRabbit

  • Breaking Changes

    • Renamed service-resolution methods to distinguish required and optional services.
    • Removed legacy service-resolution extensions from the pipeline context.
    • Updated integrations, generated code, and extensions to use the new API.
  • Bug Fixes

    • Missing required services now fail immediately with an exception instead of returning null, improving error visibility.
  • Documentation

    • Updated the v4 migration guide with the new service-resolution API.

@thomhurst

Copy link
Copy Markdown
Owner Author

@claude review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-29T03:29:53.248610Z c91e222 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 27 minutes.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e4327e8b-c9e5-4959-a95e-696579cf02aa

📥 Commits

Reviewing files that changed from the base of the PR and between c19cfab and c91e222.

📒 Files selected for processing (7)
  • RELEASE_NOTES_V4.md
  • src/ModularPipelines.Build/Modules/UnitTests/RunUnitTestModule.cs
  • src/ModularPipelines.Cmd/Extensions/CmdExtensions.cs
  • src/ModularPipelines/PublicAPI.Shipped.txt
  • src/ModularPipelines/PublicAPI.Unshipped.txt
  • test/ModularPipelines.Git.UnitTests/BranchConditionLoggingTests.cs
  • test/ModularPipelines.UnitTests/Context/ContextExtensionsTests.cs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8ef89d4f-13d9-43ad-aec6-058448f83a3c

📥 Commits

Reviewing files that changed from the base of the PR and between 81e024b and c19cfab.

📒 Files selected for processing (4)
  • RELEASE_NOTES_V4.md
  • src/ModularPipelines/PublicAPI.Shipped.txt
  • src/ModularPipelines/PublicAPI.Unshipped.txt
  • test/ModularPipelines.UnitTests/Tracing/TelemetryIntegrationTests.cs
💤 Files with no reviewable changes (1)
  • src/ModularPipelines/PublicAPI.Shipped.txt

Included review availability: Your plan provides up to 4 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The service-resolution API now distinguishes required and optional lookups. Duplicate context extensions were removed. Production consumers, generated accessors, tests, public API records, and documentation now use the new names.

Changes

Service Resolution API

Layer / File(s) Summary
Service resolution API contract
src/ModularPipelines/Context/..., src/ModularPipelines/PublicAPI.*, RELEASE_NOTES_V4.md
IServicesContext now uses GetRequiredService<T>() and nullable GetService<T>(). Duplicate context extension methods were removed. Public API records and release notes reflect the change.
Required-service call sites
src/ModularPipelines.Azure*/..., src/ModularPipelines.Build/..., src/ModularPipelines.Cmd/..., src/ModularPipelines.DotNet/..., src/ModularPipelines.Email/..., src/ModularPipelines.Ftp/..., src/ModularPipelines.Git*/..., src/ModularPipelines.MicrosoftTeams/..., src/ModularPipelines.Node/..., src/ModularPipelines.Slack/..., src/ModularPipelines.TeamCity/..., src/ModularPipelines/Context/ToolsContext.cs, src/ModularPipelines/Distributed/...
Service consumers now use required lookups where missing registrations must throw. Tool resolution uses the renamed optional lookup with its existing exception fallback.
Validation and migration support
test/..., tools/ModularPipelines.OptionsGenerator/..., docs/docs/how-to/...
Tests use real ServicesContext instances and validate required and optional lookup behavior. Generated accessors and generator tests use GetRequiredService<T>(). The migration example uses the new required lookup name.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: 🔵 Low · up to c19cf

This change renames the public service-resolution methods and makes required lookups fail immediately when a service is not registered. The PR is mergeable with explicit owner awareness that downstream callers must migrate and incomplete registrations may cause runtime failures.

Poem

A rabbit checks each service call,
Required lookups stand up tall.
Optional lookups may return null,
Old duplicate names are gone in full.
New tests hop neatly through the hall.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Most changes support [#4229], but the PR also includes unrelated API baseline additions and corrections, including PowerShell option renames, hashing and installer declarations, and telemetry test cha… Remove unrelated changes from PublicAPI.Unshipped.txt and test/ModularPipelines.UnitTests/Tracing/TelemetryIntegrationTests.cs, or link issues that explicitly require those changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 21.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 42 functions across 25 files. (2 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: aligning context service resolution with required and optional service semantics.
Linked Issues check ✅ Passed The PR satisfies the coding objectives in [#4229]. It renames the service methods to GetRequiredService() and nullable GetService(), removes the duplicate ContextExtensions methods, and updates …
Full details: Linked Issues check

Explanation

The PR satisfies the coding objectives in [#4229]. It renames the service methods to GetRequiredService<T>() and nullable GetService<T>(), removes the duplicate ContextExtensions methods, and updates callers, generated code, tests, documentation, and API baselines. The EditorBrowsable item is optional.

Full details: Out of Scope Changes check

Explanation

Most changes support [#4229], but the PR also includes unrelated API baseline additions and corrections, including PowerShell option renames, hashing and installer declarations, and telemetry test changes.

Full details: Docstring Coverage

Explanation

Docstring coverage is 21.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 42 functions across 25 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-4229-services-context

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 28, 2026

Copy link
Copy Markdown

Greptile Summary

The PR aligns pipeline service resolution with standard .NET naming while preserving required-versus-optional behavior.

  • Renames IServicesContext resolution methods and updates internal callers.
  • Removes duplicate IPipelineContext service-resolution extensions.
  • Aligns generated tool accessors, generator output, tests, documentation, and public API baselines.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/ModularPipelines/Context/Domains/IServicesContext.cs Renames the required and optional service-resolution contracts with corresponding nullability.
src/ModularPipelines/Context/Domains/Implementations/ServicesContext.cs Implements the renamed contracts while preserving existing throw and null-return semantics.
src/ModularPipelines/Context/ContextExtensions.cs Removes duplicate pipeline-context service-resolution extensions in favor of context.Services.
tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/DependencyRegistrationGenerator.cs Updates generated integration accessors to use the renamed required-service API.
src/ModularPipelines/PublicAPI.Unshipped.txt Records the removed and newly introduced public API members for compatibility validation.

Reviews (8): Last reviewed commit: "fix(api): record removed service members" | Re-trigger Greptile

@claude claude 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.

Code review

Reviewed the full diff (81e024b) against main. This is a clean, mechanical API rename that aligns IServicesContext with standard .NET DI naming/nullability conventions:

  • IServicesContext.Get<T>()GetRequiredService<T>() (throws when missing)
  • IServicesContext.TryGet<T>()GetService<T>() (nullable, returns null when missing)
  • Duplicate IPipelineContext.GetService<T>() / TryGetService<T>() extensions removed in favor of going through context.Services

Verification performed:

  • Checked out the PR branch in an isolated worktree and grepped the full tree for any remaining call sites of the old Services.Get</Services.TryGet< API and the removed IPipelineContext.GetService</TryGetService< extensions. Every call site was migrated — the handful of remaining GetService<T>() hits (OptionsValidator.cs, PipelineBuilder.cs, CliDocumentationScraperBase.cs, PluginIntegrationTests.cs) resolve to unrelated IServiceProvider/AngleSharp APIs, not the removed extension, so nothing was missed.
  • Confirmed ToolsContext.Get<T>() (a distinct, internal IToolsContext API with its own tool-registration exception) was correctly left untouched — it's out of scope for this rename and not part of the IServicesContext surface.
  • PublicAPI.Shipped.txt/PublicAPI.Unshipped.txt are updated consistently with the interface changes, the source generator (DependencyRegistrationGenerator) and its hardening test were updated to emit GetRequiredService<T>(), and RELEASE_NOTES_V4.md documents the breaking change with a before/after example.
  • Test updates (ContextExtensionsTests, BranchConditionLoggingTests, TelemetryIntegrationTests) consistently exercise the new method names and preserve the original "throws when missing / returns null when missing" semantics.

Architectural note (non-blocking): the old members are removed outright rather than routed through an [Obsolete] shim for a deprecation window. That's a reasonable call here since this lands alongside other breaking changes documented in RELEASE_NOTES_V4.md for what looks like a V4 major-version bump — bundling breaking renames into one release is preferable to a lingering obsolete surface, so no change requested.

No correctness bugs, CLAUDE.md violations, or missed call sites found.

@thomhurst

Copy link
Copy Markdown
Owner Author

@claude review

@thomhurst
thomhurst force-pushed the issue-4229-services-context branch from 81e024b to 6658410 Compare August 28, 2026 23:44
@thomhurst

Copy link
Copy Markdown
Owner Author

@claude review

@thomhurst
thomhurst force-pushed the issue-4229-services-context branch from 6658410 to e63275b Compare August 29, 2026 00:29
@thomhurst

Copy link
Copy Markdown
Owner Author

@claude please review current head e63275b.

@claude claude 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.

Code review

Re-reviewed at the current head (e63275b), which is a rebase of the previously-reviewed commit (81e024b, cleared 2026-08-28) onto the latest main (picking up #4280's logging-options unification). Diffed the two commits' content directly and confirmed the substance is unchanged:

  • IServicesContext.Get<T>()GetRequiredService<T>(), TryGet<T>()GetService<T>(), implemented consistently in ServicesContext and consumed correctly in ToolsContext.Get<T>().
  • Duplicate IPipelineContext.GetService<T>()/TryGetService<T>() extensions removed from ContextExtensions.cs in favor of context.Services.
  • All ~60 generated/manual tool-extension files updated to the new call sites, PublicAPI.Shipped.txt/PublicAPI.Unshipped.txt updated consistently, and RELEASE_NOTES_V4.md documents the breaking change with a before/after example.
  • Tests (ContextExtensionsTests, BranchConditionLoggingTests, TelemetryIntegrationTests) updated to the new names and preserve the original throw/null semantics.

Verification performed this pass: checked out the PR head commit's tree and grepped the full working tree for any remaining Services.Get<, .TryGet<, or .TryGetService< call sites — none found, confirming the rebase didn't drop or reintroduce any stale references.

Removing the old members outright rather than an [Obsolete] shim remains the right call, since this bundles into the documented V4 breaking-change set rather than adding a lingering deprecated surface.

No correctness bugs, CLAUDE.md violations, or missed call sites found.

@thomhurst

Copy link
Copy Markdown
Owner Author

Rebased onto current main. Conflicts were additive RELEASE_NOTES_V4 and PublicAPI.Unshipped entries; retained both hashing and service-resolution APIs. Validation: core build 0 warnings/errors; ContextExtensionsTests 19/19; diff check clean. @claude please review current head c19cfab.

@thomhurst
thomhurst force-pushed the issue-4229-services-context branch from e63275b to c19cfab Compare August 29, 2026 01:20

@claude claude 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.

Code review

Re-reviewed at the current head (c19cfab), which is a rebase of the previously-reviewed commit (e63275b, cleared 2026-08-29) onto the latest main (picking up #4281's PowerShell casing normalization and other recent merges). The PR branch is now a single squashed commit on top of main.

Verification performed this pass:

  • Diffed the rebased tree against main (76 files changed, +103/-149) — the substance is unchanged from the prior two reviews: IServicesContext.Get<T>()GetRequiredService<T>(), TryGet<T>()GetService<T>(), duplicate IPipelineContext.GetService<T>()/TryGetService<T>() extensions removed from ContextExtensions.cs.
  • Checked out the PR head tree and grepped for any remaining Services.Get<, Services.TryGet<, or .TryGetService< call sites — none found.
  • Confirmed ToolsContext.Get<T>() (a distinct, internal IToolsContext API) remains untouched, as it's out of scope for this rename.
  • ServicesContext.GetRequiredService<T>()/GetService<T>() implementations match what was verified in the prior reviews — throw-with-diagnostic-message vs. nullable-return semantics are preserved.
  • PublicAPI.Shipped.txt/PublicAPI.Unshipped.txt, the source generator output, RELEASE_NOTES_V4.md, and the ~60 tool-extension call sites are all consistent with the previously validated change.

No new commits were added beyond the rebase — this confirms the rebase didn't drop or reintroduce any stale references.

No correctness bugs, CLAUDE.md violations, or missed call sites found.

@thomhurst
thomhurst force-pushed the issue-4229-services-context branch from c19cfab to b7b88db Compare August 29, 2026 01:44
@thomhurst

Copy link
Copy Markdown
Owner Author

Rebased onto current main after #4274. The Git test conflict now uses this PR's GetRequiredService() with main's public ILogger context surface. Validation: core build 0 warnings/errors; ContextExtensionsTests 19/19; BranchConditionLoggingTests 3/3; diff check clean. @claude please review current head b7b88db.

@claude claude 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.

Review

This PR is a mechanical rename of the service-resolution API: IServicesContext.Get<T>()GetRequiredService<T>(), TryGet<T>()GetService<T>(), and removal of the IPipelineContext.GetService<T>()/TryGetService<T>() shortcut extensions. I verified all ~70 call-site edits across the tool packages, the core framework (src/ModularPipelines/Context/ContextExtensions.cs, Context/Domains/IServicesContext.cs, Context/Domains/Implementations/ServicesContext.cs, Context/ToolsContext.cs), the source generator (tools/ModularPipelines.OptionsGenerator/.../DependencyRegistrationGenerator.cs), and tests — all consistent, and a repo-wide grep of the PR branch found no leftover callers of the old APIs.

Blocking: PublicAPI.Shipped.txt / Unshipped.txt updated incorrectly

src/ModularPipelines/PublicAPI.Shipped.txt (around line 433) has the four removed members (IServicesContext.Get<T>(), TryGet<T>(), ContextExtensions.GetService<T>(), TryGetService<T>()) deleted outright, rather than following the Microsoft.CodeAnalysis.PublicApiAnalyzers convention of recording them as *REMOVED* entries in PublicAPI.Unshipped.txt.

Directory.Build.props enables RS0016/RS0017 as WarningsAsErrors whenever $(GITHUB_ACTIONS)=='true', so on CI, RS0017 ("Remove deleted types and members from the declared API") will fire as a build error because these four deleted signatures were never recorded with the *REMOVED* marker — only the new GetRequiredService<T>/GetService<T> entries were added to Unshipped.txt. This is very likely to break the PR's own CI build.

Suggested fix: add the removed signatures back to PublicAPI.Unshipped.txt prefixed with *REMOVED*, e.g.:

*REMOVED*ModularPipelines.Context.Domains.IServicesContext.Get<T>() -> T
*REMOVED*ModularPipelines.Context.Domains.IServicesContext.TryGet<T>() -> T
*REMOVED*ModularPipelines.Context.ContextExtensions.GetService<T>(ModularPipelines.Context.IPipelineContext! context) -> T
*REMOVED*ModularPipelines.Context.ContextExtensions.TryGetService<T>(ModularPipelines.Context.IPipelineContext! context) -> T

(adjust exact signatures to match what was in Shipped.txt) rather than deleting them from Shipped.txt directly.

@thomhurst

Copy link
Copy Markdown
Owner Author

Rebased onto current main after #4278. Conflict resolution combines ICmdContext with GetRequiredService semantics and preserves both release-note sections. Validation: core test build 0 errors; ContextExtensionsTests 18/18; Git solution build 0 warnings/errors; BranchConditionLoggingTests 3/3. Current head: 960ee9d. @claude review

@thomhurst
thomhurst force-pushed the issue-4229-services-context branch from b7b88db to 960ee9d Compare August 29, 2026 02:07

@claude claude 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.

Review

This PR is a mechanical rename of the service-resolution API: IServicesContext.Get<T>()GetRequiredService<T>(), TryGet<T>()GetService<T>(), and removal of the IPipelineContext.GetService<T>()/TryGetService<T>() shortcut extensions. I re-verified the current head (960ee9d8) against the substance already confirmed correct in prior reviews (throw-vs-nullable semantics preserved in ServicesContext/ToolsContext, all ~60 tool-extension call sites and tests updated consistently, no stray old-API references anywhere in the repo, full core-solution build succeeds).

Blocking: PublicAPI.Shipped.txt / Unshipped.txt still not following the *REMOVED* convention

This was flagged as blocking in the prior review at b7b88dbc and has not been fixed — the current head still has the same problem.

src/ModularPipelines/PublicAPI.Shipped.txt deletes the four removed members outright:

-ModularPipelines.Context.Domains.IServicesContext.Get<T>() -> T!
-ModularPipelines.Context.Domains.IServicesContext.TryGet<T>() -> T?
-static ModularPipelines.Context.ContextExtensions.GetService<T>(this ModularPipelines.Context.IPipelineContext! context) -> T!
-static ModularPipelines.Context.ContextExtensions.TryGetService<T>(this ModularPipelines.Context.IPipelineContext! context) -> T?

PublicAPI.Unshipped.txt only adds the two new members (GetRequiredService<T>, GetService<T>) — it never records the four deleted signatures as *REMOVED* entries.

Directory.Build.props:57 sets WarningsAsErrors to include RS0016;RS0017 whenever $(GITHUB_ACTIONS)=='true' (and this project's PublicApiAnalyzers package reference is gated the same way at line 44). RS0017 ("Remove deleted types and members from the declared API") will fire because these four members are gone from the API surface but were never declared as removed via the *REMOVED* prefix — this is very likely to fail the PR's own CI build.

Suggested fix: put the removed signatures back in PublicAPI.Shipped.txt (or leave them where they were) and instead add to PublicAPI.Unshipped.txt:

*REMOVED*ModularPipelines.Context.Domains.IServicesContext.Get<T>() -> T
*REMOVED*ModularPipelines.Context.Domains.IServicesContext.TryGet<T>() -> T
*REMOVED*ModularPipelines.Context.ContextExtensions.GetService<T>(ModularPipelines.Context.IPipelineContext! context) -> T
*REMOVED*ModularPipelines.Context.ContextExtensions.TryGetService<T>(ModularPipelines.Context.IPipelineContext! context) -> T

(adjust exact signatures/nullability to match what's actually in Shipped.txt today — that's the analyzer's documented convention for marking a shipped API as removed, rather than deleting the Shipped.txt line directly.)

@thomhurst
thomhurst force-pushed the issue-4229-services-context branch from 960ee9d to 8c0159e Compare August 29, 2026 02:45
@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed the current blocking review at 8c0159e. All four deleted shipped signatures are now recorded as exact *REMOVED* entries in PublicAPI.Unshipped.txt. GHA-conditioned build confirms the repository convention: keeping removed static signatures in Shipped causes RS0017, while Unshipped removal markers alone pass. Rebased onto current main and repaired CmdTests for FilePath. Validation: core test build 0 errors; Git and OptionsGenerator builds 0 errors; ContextExtensions 18/18, TelemetryIntegration 19/19, Cmd 6/6, BranchConditionLogging 3/3, GeneratorHardening 173/173; 61 PublicAPI baselines. @claude review

@claude claude 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.

Re-review at 8c0159e

Re-reviewed the current head (8c0159e0), which adds two commits on top of the previously reviewed 960ee9d8 (BLOCKING):

  • 23f1b0d2 "fix(api): record removed service members"
  • 8c0159e0 "fix(tests): use renamed file path type"

Verification performed:

  • Confirmed the previously blocking PublicAPI.Shipped.txt/Unshipped.txt issue is now fixed correctly: PublicAPI.Unshipped.txt now has *REMOVED* entries for all four removed members (IServicesContext.Get<T>(), IServicesContext.TryGet<T>(), ContextExtensions.GetService<T>(), ContextExtensions.TryGetService<T>()), matching the Microsoft.CodeAnalysis.PublicApiAnalyzers convention.
  • Built ModularPipelines.slnx (Release) against the PR branch, both normally and with GITHUB_ACTIONS=true set (which gates WarningsAsErrors for RS0016/RS0017 per Directory.Build.props) — build succeeds with 0 errors in both cases and no PublicAPI analyzer violations. This confirms the fix actually resolves the CI-breaking issue, not just superficially.
  • The remaining commit (8c0159e0) is an unrelated, correct fixup: CmdTests.GetCmdTestFile return type updated from ModularPipelines.FileSystem.File to FilePath, following the FileFilePath rename that landed in #4260 and was merged into main since this PR's earlier reviews.
  • Re-confirmed (as in prior passes) that the core rename itself — IServicesContext.Get<T>()GetRequiredService<T>(), TryGet<T>()GetService<T>(), removal of the duplicate IPipelineContext.GetService<T>()/TryGetService<T>() extensions — is fully and consistently propagated across all ~60 tool-extension call sites, the source generator template, and tests, with no stale references left anywhere in the repo.

No correctness bugs, CLAUDE.md violations, or missed call sites found. The previously blocking issue has been properly addressed.

@thomhurst
thomhurst force-pushed the issue-4229-services-context branch from 8c0159e to c91e222 Compare August 29, 2026 03:26
@thomhurst

Copy link
Copy Markdown
Owner Author

Rebased onto main after #4273 merged; resolved RELEASE_NOTES_V4.md additively, retaining both requirements and service-resolution guidance. Validation: ModularPipelines.Tests.slnf Release build passed with 0 errors; ContextExtensionsTests passed 18/18; no conflict markers or diff-check errors. @claude please review the new head.

@claude claude 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.

Code review

Re-reviewed at the current head (c91e222), which rebases the previously-cleared 8c0159e0 onto main after #4273 merged. Diffed the rebased tree against main (76 files, +106/-149) and confirmed the substance is unchanged from the five prior review passes on this PR:

  • IServicesContext.Get<T>()GetRequiredService<T>() (throws when missing), TryGet<T>()GetService<T>() (nullable), implemented consistently in ServicesContext and consumed correctly by ToolsContext.Get<T>().
  • Duplicate IPipelineContext.GetService<T>()/TryGetService<T>() extensions removed from ContextExtensions.cs in favor of context.Services.
  • All ~70 tool-extension call sites updated consistently; grepped the rebased tree for any remaining Services.Get</Services.TryGet</.TryGetService< references — none found.

Previously-blocking issue confirmed still fixed: the PublicAPI.Shipped.txt/Unshipped.txt handling (flagged blocking at b7b88dbc and 960ee9d8, fixed at 8c0159e0) remains correct at this head — the four removed members are recorded as *REMOVED* entries in PublicAPI.Unshipped.txt rather than deleted outright from Shipped.txt, matching the PublicApiAnalyzers convention that satisfies RS0017 under CI's WarningsAsErrors.

Test changes since the last review are a genuine improvement, not just mechanical renames: ContextExtensionsTests now builds a real ServiceCollection/ServicesContext and asserts against it directly, rather than mocking IModuleContext/IServicesContext and mocking the now-removed IPipelineContext.GetService<T>() extension. Since the extension being tested no longer exists, exercising the real DI container end-to-end is a better fit than a mock would have been here — it validates actual IServiceProvider resolution behavior instead of a hand-configured mock returning a canned value.

RELEASE_NOTES_V4.md documents the breaking change with a clear before/after example, consistent with the rest of the V4 migration guide.

No correctness bugs, CLAUDE.md violations, or missed call sites found. No architectural concerns beyond what was already discussed and resolved in prior rounds (removing the old members outright rather than an [Obsolete] shim remains the right call, since this bundles into the documented V4 breaking-change set).

@thomhurst
thomhurst merged commit 72c0caf into main Aug 29, 2026
16 checks passed
@thomhurst
thomhurst deleted the issue-4229-services-context branch August 29, 2026 03:57
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.

v4: context.GetService<T>() throws — align with the GetService/GetRequiredService convention and drop the ContextExtensions duplicates

1 participant