Skip to content

Extract duplicated channel helpers into Netclaw.Channels - #2002

Merged
Aaronontheweb merged 3 commits into
devfrom
refactor/channel-warmups
Aug 19, 2026
Merged

Extract duplicated channel helpers into Netclaw.Channels#2002
Aaronontheweb merged 3 commits into
devfrom
refactor/channel-warmups

Conversation

@Aaronontheweb

@Aaronontheweb Aaronontheweb commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

What

Phase 2 of the code-reduction stack (on top of #2000). Consolidates five helper groups that the Slack, Discord, and Mattermost channel code duplicated. Behavior is unchanged. No shared actor base class is introduced — that is a later phase.

Shared construct (new, in Netclaw.Channels) Replaces
MessageChunker.Chunk(text, maxLength) Byte-identical chunkers in Discord + Mattermost binding actors (each keeps its own max-length constant; Slack posts unchunked and is untouched)
UserQueryNormalizer.StripLeadingAt Byte-identical 3-liners in LookupSlackUserTool + LookupMattermostUserTool; DiscordAddressResolver keeps its mention-tag path and delegates the non-mention path
PendingApprovalRequest<TPromptId> Triplicate in-memory pending-approval class (Discord/Mattermost/Slack). Each channel keeps a thin sealed subclass that exposes its transport-specific property name. The journaled PendingApprovalPromptTracked/Cleared types are untouched — no wire-compat impact
PendingApprovalLookup.Resolve Byte-identical ResolvePendingRequest + ApprovalLookupResult in Discord + Mattermost. The ApprovalButtonValueCodec.CanApprove requester check now has one copy instead of two. Slack's lookup has a genuinely different shape and stays as-is
PendingApprovalRecovery.ApplyTracked/ApplyCleared Cold-spawn recovery replay handlers in all three actors. _hasObservedApprovalRequest stays actor-local

Why

These triplicated regions are where fixes historically land in one channel and miss the others. Centralizing the approval lookup and recovery replay means a future security fix to the requester check cannot drift between channels. This also stages the ground for the larger binding-actor consolidation planned in a later phase of this stack.

Verification

  • Full Netclaw.Actors.Tests suite: 3,439 passed, 0 failed, 1 skipped (pre-existing Windows-only skip)
  • Targeted: SessionBindingContractTests + ApprovalRehydrationTests (172), chunking/contract/serialization suites (254), ChannelRegistryRegistrationTests (21) — all green
  • dotnet slopwatch analyze: 0 issues; header verification passes

Stack

PR 2 of 4. Base: refactor/test-compression (#2000). Next: NotifyDeliveryFailedAsync drift fix.

Collapse groups of near-identical [Fact] methods into [Theory] methods
with MemberData or InlineData rows. Extract repeated arrange blocks into
shared helpers. Each old fact maps to exactly one theory row. All
assertions and input literals are unchanged. No production code changes.

Files:
- Cli.Tests: ExposureModeDoctorCheckTests, ConfigSchemaDoctorCheckTests,
  WebhooksCommandTests, ApprovalsCommandTests, ChannelsConfigViewModelTests
- Daemon.Tests: RetryingChatClientTests
- Security.Tests: ToolPathPolicyTests, MagicByteValidatorTests,
  RegexPromptInjectionDetectorTests
- Actors.Tests: DispatchingToolExecutorTests, WebFetchToolTests,
  ReminderManagerActorTests (helper extraction only)
- ConfigEditorCoverageAuditTests: update nameof references to the merged
  theory
Consolidate five helper groups that Slack, Discord, and Mattermost
duplicated. Behavior is unchanged. No shared actor base class is
introduced.

- MessageChunker: one newline-aware chunk algorithm for Discord and
  Mattermost. Each actor keeps its own max-length constant.
- UserQueryNormalizer.StripLeadingAt: one strip-at helper for the Slack
  and Mattermost lookup tools. Discord keeps its mention-tag path.
- PendingApprovalRequest<TPromptId>: one generic base for the in-memory
  pending-approval record. Each channel keeps a thin subclass with its
  transport-specific property name. The journaled types are untouched.
- PendingApprovalLookup.Resolve: one copy of the approval lookup. The
  ApprovalButtonValueCodec.CanApprove requester check now lives in one
  place for Discord and Mattermost.
- PendingApprovalRecovery.ApplyTracked/ApplyCleared: one copy of the
  cold-spawn recovery replay for all three channels.
@Aaronontheweb
Aaronontheweb force-pushed the refactor/channel-warmups branch from f6f3f4c to c3c857d Compare August 19, 2026 02:08
@Aaronontheweb
Aaronontheweb marked this pull request as ready for review August 19, 2026 02:09
@Aaronontheweb Aaronontheweb added channels Discord, Slack, and other channels. cleanup Code quality improvements and tech debt reduction labels Aug 19, 2026
Base automatically changed from refactor/test-compression to dev August 19, 2026 02:51
@Aaronontheweb
Aaronontheweb force-pushed the refactor/channel-warmups branch 2 times, most recently from 66a0437 to c3c857d Compare August 19, 2026 03:39
@Aaronontheweb
Aaronontheweb merged commit 9d5f059 into dev Aug 19, 2026
31 of 33 checks passed
@Aaronontheweb
Aaronontheweb deleted the refactor/channel-warmups branch August 19, 2026 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channels Discord, Slack, and other channels. cleanup Code quality improvements and tech debt reduction refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant