Skip to content

ci: bump actions/setup-dotnet from 4 to 5#3

Merged
joshsmithxrm merged 1 commit intomainfrom
dependabot/github_actions/actions/setup-dotnet-5
Dec 16, 2025
Merged

ci: bump actions/setup-dotnet from 4 to 5#3
joshsmithxrm merged 1 commit intomainfrom
dependabot/github_actions/actions/setup-dotnet-5

Conversation

@dependabot
Copy link
Copy Markdown
Contributor

@dependabot dependabot bot commented on behalf of github Dec 14, 2025

Bumps actions/setup-dotnet from 4 to 5.

Release notes

Sourced from actions/setup-dotnet's releases.

v5.0.0

What's Changed

Breaking Changes

Make sure your runner is updated to this version or newer to use this release. v2.327.1 Release Notes

Dependency Updates

Bug Fixes

New Contributors

Full Changelog: actions/setup-dotnet@v4...v5.0.0

v4.3.1

What's Changed

Full Changelog: actions/setup-dotnet@v4...v4.3.1

v4.3.0

What's Changed

New Contributors

... (truncated)

Commits
  • 2016bd2 Bump actions/publish-action from 0.3.0 to 0.4.0 and update macos-13 to macos-...
  • 21e81f6 Bump eslint-plugin-jest from 27.9.0 to 29.0.1 (#648)
  • 7403103 Bump typescript from 5.4.2 to 5.9.2 (#624)
  • d4c9434 Update to Node.js 24 and modernize async usage (#654)
  • 5c125af Bump actions/checkout from 4 to 5 (#662)
  • 87c6e11 Bumps form-data (#652)
  • 06a5327 Bump undici from 5.28.5 to 5.29.0 (#641)
  • e8e5b82 Bump eslint-config-prettier from 9.1.0 to 10.1.5 (#639)
  • bf4cd79 Bump @​actions/glob from 0.4.0 to 0.5.0 (#594)
  • 4ddad1c Bump husky from 8.0.3 to 9.1.7 (#591)
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot merge will merge this PR after your CI passes on it
  • @dependabot squash and merge will squash and merge this PR after your CI passes on it
  • @dependabot cancel merge will cancel a previously requested merge and block automerging
  • @dependabot reopen will reopen this PR if it is closed
  • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4 to 5.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](actions/setup-dotnet@v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot @github
Copy link
Copy Markdown
Contributor Author

dependabot bot commented on behalf of github Dec 14, 2025

Labels

The following labels could not be found: dependencies, github-actions. Please create them before Dependabot can add them to a pull request.

Please fix the above issues or remove invalid values from dependabot.yml.

@joshsmithxrm joshsmithxrm merged commit ef054ee into main Dec 16, 2025
2 checks passed
@dependabot dependabot bot deleted the dependabot/github_actions/actions/setup-dotnet-5 branch December 16, 2025 16:39
joshsmithxrm added a commit that referenced this pull request Jan 2, 2026
- Remove unused roleNameCache from RelationshipProcessor (#1)
  The cache was built with a network call but never used since
  LookupRoleByIdAsync queries by ID directly, not by name.

- Add volatile to AuthenticationOutput._writer (#3)
  Ensures thread-safe reads/writes of the static field.

- Unify ProfileConnectionSource locking (#4)
  Both sync and async paths now use the same SemaphoreSlim lock,
  preventing race conditions between GetSeedClient and GetSeedClientAsync.
  Also marked _seedClient as volatile for proper double-checked locking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 2, 2026
* fix: add thread-safe async locking to ProfileConnectionSource

Add SemaphoreSlim for proper async synchronization in GetSeedClientAsync.
The previous implementation checked _seedClient outside any lock, allowing
concurrent calls to create duplicate providers and clients.

Changes:
- Add _asyncLock SemaphoreSlim for async method synchronization
- Implement double-check locking pattern in GetSeedClientAsync
- Dispose SemaphoreSlim in Dispose method

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: use ConcurrentBag for thread-safe provider tracking

Replace List<ICredentialProvider> with ConcurrentBag<ICredentialProvider>
to prevent collection corruption when CreateFromProfileAsync is called
concurrently from multiple threads.

Changes:
- Add System.Collections.Concurrent using
- Change _activeProviders to ConcurrentBag<ICredentialProvider>
- Update Dispose to use TryTake pattern instead of Clear()

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: properly unregister MSAL cache in InteractiveBrowserCredentialProvider

Unregister the MsalCacheHelper from the token cache during disposal to
release file locks on the token cache file.

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: properly unregister MSAL cache in GlobalDiscoveryService

Unregister the MsalCacheHelper from the token cache during disposal to
release file locks on the token cache file.

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: remove redundant CancellationTokenSource from Program.cs

System.CommandLine 2.x handles Ctrl+C automatically and passes the
cancellation token to command handlers via SetAction's cancellationToken
parameter. The manual CancelKeyPress handler was creating a CTS that was
never connected to the command invocation pipeline.

Removed the unused CTS and added a clarifying comment about how
cancellation is handled.

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: use ConcurrentDictionary for entity type code cache

Replace Dictionary<string, int> with ConcurrentDictionary<string, int>
for the _entityTypeCodeCache to ensure thread-safe access in case of
concurrent operations.

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: extract duplicate ParseBypassPlugins to DataCommandGroup

Move the ParseBypassPlugins method from ImportCommand and CopyCommand
to DataCommandGroup as a shared internal helper. Both commands now
reference the single implementation.

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: suppress NU1702 warning for cross-framework PPDS.Plugins reference

PPDS.Plugins must target net462 (Dataverse plugin sandbox requirement) but
is referenced by projects targeting net8.0+. Since the package contains only
attributes and enums with no framework-specific APIs, this cross-framework
reference is intentional and safe.

Added explanatory comments in each affected project file.

Fixes part of #71

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: remove NU1903 vulnerability warning suppression

The high-severity vulnerability in transitive dependencies has been fixed
upstream. Remove the suppression so future vulnerabilities are properly
reported.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: use X509CertificateLoader for .NET 9+ certificate loading

Replace deprecated X509Certificate2 constructor with X509CertificateLoader
on .NET 9+. Uses conditional compilation to maintain compatibility with
.NET 8.

Fixes SYSLIB0057 warnings on net9.0 and net10.0 targets.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: suppress SYSLIB0014 warning for ServicePointManager

ServicePointManager is obsolete in .NET 6+, but these settings are required
for optimal Dataverse throughput. The Dataverse SDK uses HttpWebRequest
internally, so these settings still apply. No alternative exists until
Microsoft updates their SDK to use HttpClient.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use async/await in thread safety tests (xUnit1031)

Convert blocking Task.WaitAll() to async Task.WhenAll() to resolve
xUnit1031 analyzer warnings about potential deadlocks in test methods.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: address 11 code review findings from #80

Critical fixes:
- Fix copy-paste bug in CertificateStoreCredentialProvider (StoreName→StoreLocation)
- Fix memory leak in DeviceCodeCredentialProvider.Dispose() (unregister cache)
- Fix memory leak in UsernamePasswordCredentialProvider.Dispose() (unregister cache)
- Fix double-checked locking bug in ConnectionStringSource (add volatile)

High priority fixes:
- Add debug logging for expected role lookup failures in TieredImporter
- Remove duplicate endpoint lookup in GlobalDiscoveryService
- Remove dead code ExecuteBatchesParallelAsync (76 lines)

Medium priority fixes:
- Redact exception messages in TieredImporter using ConnectionStringRedactor
- Add validation for empty entity/field names in CmtSchemaReader
- Add validation for MaxParallelEntities >= 1 in ImportOptions
- Preserve FaultException error codes in BulkOperationExecutor

Closes #80

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add AuthenticationOutput for configurable auth messaging (#80)

Addresses issues #7, #9, #15, #27 from code review:

- #7: Add thread-safety remarks to ConsoleProgressReporter
- #9: Add documentation for role mapping limitation in TieredImporter
- #15: Replace Console.WriteLine with AuthenticationOutput in auth library
  - New AuthenticationOutput class allows consumers to redirect or suppress output
  - Set AuthenticationOutput.Writer = null to suppress, or provide custom Action<string>
- #27: Add validation in CredentialProviderFactory before null-forgiveness
  - ValidateRequiredFields checks GitHubFederated, AzureDevOpsFederated, UsernamePassword

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: address remaining issue 71 code review findings (8, 12)

Issue 8: Wrap sync-over-async in Task.Run to avoid deadlock
- ProfileConnectionSource.GetSeedClient() now runs async code on
  threadpool to prevent deadlock in sync contexts (UI/ASP.NET)

Issue 12: Use Uri.TryCreate instead of try-catch for flow control
- AuthCommandGroup.ExtractEnvironmentName() refactored to avoid
  exception-based control flow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: extract phase processors from TieredImporter (#18)

Extract schema validation, deferred field processing, and relationship
processing into separate classes to improve testability and maintainability.

New components:
- ISchemaValidator/SchemaValidator: Load target metadata, detect mismatches
- DeferredFieldProcessor: Process self-referential lookup updates
- RelationshipProcessor: Process M2M associations with role mapping
- ImportContext: Shared context for all import phases
- FieldMetadataCollection: Type-safe wrapper for field validity data
- SchemaMismatchResult: Result type with detailed error message builder
- IImportPhaseProcessor/PhaseResult: Common interface for phase processors

TieredImporter reduced from 1,085 to 646 lines, now focused on orchestration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: address PR review feedback (issues 1, 3, 4)

- Remove unused roleNameCache from RelationshipProcessor (#1)
  The cache was built with a network call but never used since
  LookupRoleByIdAsync queries by ID directly, not by name.

- Add volatile to AuthenticationOutput._writer (#3)
  Ensures thread-safe reads/writes of the static field.

- Unify ProfileConnectionSource locking (#4)
  Both sync and async paths now use the same SemaphoreSlim lock,
  preventing race conditions between GetSeedClient and GetSeedClientAsync.
  Also marked _seedClient as volatile for proper double-checked locking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 2, 2026
- Use shlex.split for robust git commit detection (#2)
- Print both stdout and stderr on build/test failure (#3, #4)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 2, 2026
* docs: add Claude workflow automation and streamline CLAUDE.md

- Add /pre-pr command for pre-commit validation (build, test, changelog check)
- Add /review-bot-comments command for triaging bot review findings
- Add pre-commit hook to validate builds/tests before commit
- Update development workflow to reference new commands
- Streamline CLAUDE.md (remove verbose namespace examples, simplify comments section)
- Add testing requirements table showing coverage gaps (Auth, Migration need tests)
- Add bot review handling guidance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: minor refinements to hook and CLAUDE.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: improve pre-commit hook robustness

- Add warning message on JSON parse failure (#9)
- Handle FileNotFoundError when dotnet not in PATH (#1, #12)
- Add 5-minute timeout to subprocess calls (#11)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: improve pre-commit hook command detection and output

- Use shlex.split for robust git commit detection (#2)
- Print both stdout and stderr on build/test failure (#3, #4)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: simplify gh api permission in settings example

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 3, 2026
- Use shlex.split for robust git commit detection (#2)
- Print both stdout and stderr on build/test failure (#3, #4)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 6, 2026
- Add /triage slash command for batch issue categorization
- Create issue templates (feature_request.yml, bug_report.yml)
- Add comprehensive ROADMAP.md with triage guidelines
- Update CLAUDE.md with roadmap documentation
- Establish label taxonomy (removed 6 deprecated, added 7 area labels)
- Move existing phase planning to FEATURE_ROADMAP.md

Integrates with PPDS Roadmap project (#3) to assign Type, Priority, Size,
Status, and Target fields to issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 6, 2026
* feat: add GitHub issue triage system with /triage command

- Add /triage slash command for batch issue categorization
- Create issue templates (feature_request.yml, bug_report.yml)
- Add comprehensive ROADMAP.md with triage guidelines
- Update CLAUDE.md with roadmap documentation
- Establish label taxonomy (removed 6 deprecated, added 7 area labels)
- Move existing phase planning to FEATURE_ROADMAP.md

Integrates with PPDS Roadmap project (#3) to assign Type, Priority, Size,
Status, and Target fields to issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: skip CI workflows for docs-only changes

Add paths-ignore filters to build, test, and integration-tests workflows
to skip execution when only documentation files are modified:

- docs/**
- .claude/**
- *.md
- .github/ISSUE_TEMPLATE/**

This prevents wasteful CI runs for documentation updates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: address bot review comments on PR #229

- Add Parent Issue column to triage template table
- Add note on how to update hardcoded project field IDs
- Add bash syntax highlighting to code block
- Fix incorrect path reference (remove sdk/ prefix)
- Clarify "SDK CLAUDE.md" to just "CLAUDE.md"

Addresses all 5 bot findings from Gemini and Copilot reviews.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: add gh issue create to allowlist

Allow creating GitHub issues without permission prompt.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 7, 2026
Add NEVER rule and clarify ALWAYS rule to prevent GitHub's auto-close
syntax limitation where comma-separated issues (Closes #1, #2, #3) only
closes the first issue.

Closes #153
Closes #154
Closes #155
Closes #156
Closes #157
Closes #158

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 7, 2026
Add NEVER rule and clarify ALWAYS rule to prevent GitHub's auto-close
syntax limitation where comma-separated issues (Closes #1, #2, #3) only
closes the first issue.

Closes #153
Closes #154
Closes #155
Closes #156
Closes #157
Closes #158

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Jan 8, 2026
joshsmithxrm added a commit that referenced this pull request Jan 8, 2026
Implements HIGH and MEDIUM priority settings from Bug #3 audit:

HIGH PRIORITY (4 settings):
- virtualTable.initialPageSize (10-500, default: 100)
- virtualTable.maxCachedRecords (100-100000, default: 10000)
- webResources.cacheTTL (10-600s, default: 60s)
- api.maxRetries (0-10, default: 3)

MEDIUM PRIORITY (4 settings):
- pluginTrace.batchDeleteSize (50-1000, default: 100)
- pluginTrace.defaultDeleteOldDays (1-365, default: 30)
- virtualTable.backgroundPageSize (100-2000, default: 500)
- metadata.cacheDuration (60-3600s, default: 300s)

LOW priority settings deferred to docs/future/INFRASTRUCTURE.md

Also fixes Bug #4: Filter panel sizing issue
- Capture height BEFORE toggling collapsed class
joshsmithxrm added a commit that referenced this pull request Jan 8, 2026
* docs: audit roadmap and create tracking for v0.3.0 feature completion

- Create FINISH_FEATURES_TODO.md tracking document for branch work
- Update DATA_MANAGEMENT.md: Data Explorer core marked implemented,
  IntelliSense/Aggregates/JOINs/Saved Queries as planned for v0.3.0
- Update DEVELOPMENT_TOOLS.md: Web Resources marked fully implemented,
  remaining items are conflict detection, JS validation, retry logic
- Update METADATA_BROWSER_ENHANCEMENTS.md: Core marked implemented,
  solution filtering and CSV export planned
- Update INFRASTRUCTURE.md: Review status confirmed
- Update future/README.md: Status table with implementation checkmarks

Scope for this branch:
- Web Resources: conflict detection, JS validation, retry logic (~6-9h)
- Metadata Browser: solution filtering, CSV export (~7-10h)
- Data Explorer: IntelliSense, Aggregates, JOINs, Saved Queries (~40-55h)

Deferred to ALM/Deployment Settings work:
- Local folder sync for Web Resources

* feat(web-resources): add conflict detection for concurrent edits

Warn users when saving a web resource that was modified by another user
since they opened it. Shows modal with options: Overwrite, Reload from
Server, or Cancel.

Changes:
- Add getModifiedOn() to IWebResourceRepository for lightweight timestamp check
- Extend WebResourceContentResult to include modifiedOn timestamp
- Store server's modifiedOn in FileSystemProvider cache
- Check for conflicts before each save, show warning modal if detected
- Refresh modifiedOn after successful save to track new baseline

Also documents bug: FileSystemProvider uses wrong connection when multiple
panels open with different auth contexts (to be fixed in next commit).

* fix(web-resources): add HTTP cache prevention to all API calls

- Add Cache-Control and Pragma headers to prevent HTTP caching
- Add cache: 'no-store' to all fetch() calls
- Fixed in: DataverseApiService (main + batch), WhoAmIService, PowerPlatformApiService
- Admin/developer tools must never show stale data

Also includes FileSystemProvider refactor from previous session:
- WebResourceConnectionRegistry for multi-environment support
- stat() optimization (no longer calls readFile)
- VS Code document caching workarounds

Note: 3 unit tests failing due to removed TTL caching behavior (tracked in docs)

* fix(web-resources): fetch unpublished content and fix reload from server

- Change getContent() to use RetrieveUnpublished bound function
  so developers see their latest saved changes (even before publish)
- Fix "Reload from Server" to properly update editor content
  by using WorkspaceEdit instead of unreliable revert command
- Add test coverage for reload from server conflict resolution

* feat(web-resources): detect unpublished changes on file open

When opening a web resource, compares published vs unpublished content.
If different, opens VS Code's merge editor to let user choose version.

Changes:
- Add getPublishedContent() to IWebResourceRepository
- Add mode support in FileSystemProvider URIs (published/unpublished/conflict)
- Open merge editor when unpublished changes detected
- Fetch both versions in parallel for comparison

* docs: add web resource version selection UX design

Documents two processes for handling version differences:
1. Opening files with unpublished changes (choose starting point)
2. Save conflicts when server modified (conflict resolution)

Both use "select one file" approach with diff view for comparison.
Merge editor rejected as overkill for typical use cases.

Design ready for implementation in next session.

* feat(web-resources): implement version selection UX for conflicts

Process 1 - Opening with unpublished changes:
- Show diff view (Published left, Unpublished right)
- Non-modal notification: "Edit Unpublished" / "Edit Published" / "Cancel"
- Close diff and open chosen version as editable file

Process 2 - Save conflict detection:
- Add "Compare First" option to conflict modal (reordered as primary)
- Show diff view (Server left, Local right) with non-modal buttons
- "Save My Version" / "Use Server Version" / "Cancel"

Technical implementation:
- Add 'server-current' and 'local-pending' content modes to URI scheme
- Add pendingSaveContent map for temporary storage during diff
- Non-modal notifications allow scrolling diff while deciding

* fix(web-resources): add syntax highlighting for opened files

VS Code doesn't auto-detect language mode for custom URI schemes.
Added setTextDocumentLanguage call after opening documents to enable
syntax highlighting based on file extension (.js, .ts, .css, .html, etc.)

* feat(web-resources): add Created By and Modified By columns

- Add createdBy/modifiedBy fields to WebResource entity
- Update repository to fetch user names via $expand on createdby/modifiedby
- Update ViewModel and mapper for table display
- Update tests across all layers

docs: update roadmap for v0.3.0
- Mark Web Resources and Metadata Browser as complete
- Move solution filtering to Solution Explorer (future)
- Defer Excel export (bundle size concern)
- Only Data Explorer remains (~40-55h)

* docs: clarify HTTP cache prevention is defensive measure, not bug fix

- Update comments in DataverseApiService to explain cache prevention
  is for admin tool reliability, not fixing a specific bug
- Update tracking doc to reflect that the original "stale content"
  issue was caused by Dataverse returning published content (fixed
  by RetrieveUnpublished), not HTTP caching
- Remove duplicate Decision Log section from tracking doc
- Add decision log entry documenting the clarification

* fix(panels): refresh solution dropdown on environment switch

When switching environments, the solution dropdown retained stale
solutions from the previous environment instead of loading solutions
for the new environment.

Root causes fixed:
- messaging.js had no handler for updateSolutionSelector message
- Connection References panel didn't call loadSolutions() on env change

Added regression tests to prevent future regressions.

* docs: add FileSystemProvider complexity to technical debt

- Add low-priority item for WebResourceFileSystemProvider (~800 lines)
- Document proposed solution: extract ConflictResolver and ContentModeHandler
- Trigger: when adding new content modes or conflict features
- Update README.md counts and file structure

* fix(web-resources): simplify conflict resolution reload flow

- Remove unnecessary waitForPendingFetch + notifyFileChanged + revert
  pattern from panel (VS Code fetches fresh content without it)
- Simplify reloadFromServer() to close editor and reopen with fresh
  unpublished URI (fixes bug where ?mode=published was being loaded)
- Remove unused waitForPendingFetch() and notifyFileChanged() methods
- Update tests to match new reload behavior

Note: There is still a timing issue where VS Code shows stale content
briefly before readFile() completes. This needs further investigation.

* docs: remove references to removed VS Code caching workaround

* feat(web-resources): add pre-fetch, publish prompt, and defensive logging

- Pre-fetch content before opening document in reloadFromServer()
  to eliminate flicker when choosing "Use Server Version"
- Add publish prompt when user opens file with unpublished changes
  and chooses "Edit Unpublished" version
- Add defensive logging for external content changes detected
  during VS Code auto-refresh
- Document expected VS Code "content is newer" dialog behavior
  after auto-refresh (VS Code's built-in protection, not a bug)

* fix(web-resources): use WorkspaceEdit to reload server content on conflict

The "Use Server Version" option during conflict resolution was not
showing the server content - VS Code cached the dirty document content
and didn't call readFile after revert.

Changes:
- Replace revert approach with WorkspaceEdit.replace() to directly
  update document buffer, bypassing VS Code's caching
- Remove redundant closeActiveEditor call that was prompting to save
- Use setImmediate to defer document.save() and avoid deadlock when
  clearing the dirty flag (nested writeFile calls)
- Store normalized document content (after VS Code applies edit) as
  lastKnownContent to ensure contentEquals matches on save

Add regression tests verifying WorkspaceEdit is used for reload.

* fix(panels): show loading immediately on environment switch

Clear stale data and show loading indicator at the START of
handleEnvironmentChange(), before async operations begin.

Previously, users saw ~1 second of stale data from the previous
environment while solutions and metadata were being fetched.

* fix(panels): show loading placeholder in solution dropdown on env switch

When switching environments, immediately show "Loading solutions..."
placeholder and disable the dropdown to prevent selecting stale
solutions from the previous environment.

The dropdown re-enables when actual solutions are loaded.

* docs: update CHANGELOG with unreleased features and fixes

Add entries for Web Resources conflict detection, unpublished changes
detection, Created By/Modified By columns, environment switch loading
state improvements, solution dropdown refresh fix, and syntax highlighting.

* fix(panels): implement SafeWebviewPanel and two-level cancellation

Problem:
- Closing panels during long-running API requests caused "Webview is disposed" errors
- API requests continued running after panel closure, wasting server resources
- Paginated fetches (5000+ records per page) kept making requests after disposal

Solution:
- SafeWebviewPanel wrapper that tracks disposal and provides safe postMessage()
- ISafePanel interface for behaviors to use safe messaging
- AbortSignalCancellationTokenAdapter to convert panel abort signal to cancellation token
- CompositeCancellationToken to combine panel-level and operation-level cancellation
- Two-level cancellation in WebResourcesPanelComposed:
  - Level 1: Panel closes → all operations cancelled via abortSignal
  - Level 2: User changes solution/environment → previous operation cancelled

Files added:
- SafeWebviewPanel.ts - wrapper with disposal tracking and safe postMessage
- ISafePanel.ts - interface for safe panel operations
- AbortSignalCancellationTokenAdapter.ts - adapts AbortSignal to ICancellationToken
- CompositeCancellationToken.ts - combines multiple cancellation tokens

Updated:
- All 11 panel classes to use SafeWebviewPanel
- All behavior classes to use ISafePanel
- PanelCoordinator to use SafeWebviewPanel
- WebResourcesPanelComposed with full two-level cancellation

* docs: add panel disposal cancellation fix to CHANGELOG

* docs: add Data Explorer v0.3.0 requirements and update design

Requirements (DATA_EXPLORER_V03_REQUIREMENTS.md):
- 5 phases: IntelliSense, Query History, Aggregates/JOINs, INSERT/UPDATE/DELETE, Visual Query Builder
- Design decisions: hybrid history UI, batch size 100, personal views only
- Current architecture documented (SQL ↔ FetchXML bidirectional modes)
- Three-mode architecture for Phase 5 (SQL | FetchXML | Visual)
- Estimated effort: 62-90 hours

IntelliSense Design (V2.1 updates):
- Added SqlEditorWatcher for panel-editor sync
- Added Ctrl+Enter keybinding for query execution
- Clarified two-mode architecture (SQL in VS Code, FetchXML in panel)
- Added future phase keywords (INSERT, UPDATE, DELETE, aggregates)
- Added future phase considerations section

Progress Tracking:
- Updated Data Explorer section with 5-phase breakdown
- Added 7 new design decisions to Decision Log
- Added session progress for 2025-12-04

* feat(data-explorer): implement IntelliSense core components

Phase 1 of Data Explorer IntelliSense implementation:

Domain Layer:
- EntitySuggestion, AttributeSuggestion value objects
- SqlContextDetector domain service (detects completion context)
- IIntelliSenseMetadataRepository interface

Application Layer:
- IntelliSenseContextService (tracks active environment)
- IntelliSenseMetadataCache (caches metadata with TTL)
- GetEntitySuggestionsUseCase, GetAttributeSuggestionsUseCase

Infrastructure Layer:
- DataverseIntelliSenseMetadataRepository (OData API calls)

Presentation Layer:
- DataverseCompletionProvider (VS Code completion provider)
- SqlEditorService (opens new SQL queries and files)
- SqlEditorWatcher (watches editor changes for sync)

Tests:
- Full test coverage for domain and application layers
- All 494 Data Explorer tests pass

Remaining: Extension registration, panel integration, Ctrl+Enter keybinding

* feat(data-explorer): complete Phase 1 IntelliSense integration

- Register completion provider for ALL SQL files (singleton pattern)
- Add New Query and Open File buttons to panel toolbar
- Wire IntelliSenseContextService to panel environment changes
- Add Ctrl+Enter keybinding for query execution from VS Code editor
- Connect SqlEditorWatcher for FetchXML preview sync with external editor
- Add query execution request events to IntelliSenseContextService

Phase 1 of Data Explorer IntelliSense is now complete:
- Entity/attribute completions work in native VS Code SQL files
- Panel integrates with external SQL editor for FetchXML preview
- Users can execute queries from VS Code with Ctrl+Enter

* fix(data-explorer): improve IntelliSense context detection for partial typing

The SqlContextDetector was only detecting attribute context when cursor
was immediately after keywords (SELECT, WHERE, etc.) with trailing whitespace.
This caused completions to stop working as soon as the user started typing.

Changed from exact position matching to REGION-based detection:
- SELECT column list region (between SELECT and FROM)
- WHERE clause region (after WHERE/AND/OR, before operators)
- ORDER BY region (after ORDER BY)

Now completions work correctly when:
- Typing partial attribute name: "SELECT na|me FROM account"
- Editing after writing full query: go back to modify columns
- Adding columns after comma: "SELECT name, acc| FROM account"

Added 7 new tests for partial typing scenarios.

* feat(data-explorer): add Dataverse SQL Notebooks POC

Implement VS Code notebook support for SQL queries against Dataverse:

- Add .dataverse-sql notebook file format with custom serializer
- Create notebook controller for cell execution
- Render results as theme-aware HTML tables using VS Code CSS variables
- Environment selection via status bar picker
- Persist environment in notebook metadata
- Add "New Dataverse SQL Notebook" command

Known limitation: IntelliSense uses global environment context, not
per-notebook. Tracked in docs/work/DATAVERSE_SQL_NOTEBOOKS_TODO.md.

* feat(data-explorer): integrate notebooks with Data Explorer panel

- Add "Open in Notebook" button to Data Explorer toolbar
- Export openQueryInNotebook function for panel integration
- Notebook inherits environment and SQL from panel
- Pre-populate notebook with panel's current query

* style(notebooks): match Data Explorer table styling

Update notebook results HTML to match Data Explorer panel:
- Blue header background (--vscode-button-background)
- Alternating row colors for readability
- Consistent cell padding and borders
- Status bar with row count and execution time
- Link styling matching panel
- Sticky header for scrolling

* fix(notebooks): auto-size table columns to content

* fix(notebooks): remove special styling for primary key column

* feat(notebooks): add clickable links and rename to .ppdsnb

- Add clickable links for lookup fields (opens record in browser)
- Add clickable links for primary key columns (e.g., accountid)
- Store environment URL in notebook metadata for link generation
- Rename notebook extension from .dataverse-sql to .ppdsnb
- Update display name to "Power Platform Developer Suite Notebook"

* feat(notebooks): add FetchXML cell support with custom language

- Support both SQL and FetchXML cells in notebooks
- Register custom 'fetchxml' language with XML syntax highlighting
- Language picker now shows "FetchXML" instead of generic "XML"
- Detect cell language and route to appropriate use case:
  - SQL cells: transpile to FetchXML then execute
  - FetchXML cells: execute directly
- Add content-based detection for cells starting with <fetch
- Preserve cell language in serializer (sql/fetchxml/markdown)

* feat(intellisense): add FetchXML IntelliSense support

Implement context-aware IntelliSense for FetchXML queries:
- Element suggestions based on parent element hierarchy
- Attribute name suggestions for each element type
- Attribute value suggestions (entity names, attribute names, operators)
- 70+ condition operators with descriptions and categories
- 41 unit tests for context detection

* refactor(notebooks): rename SqlNotebook to Notebook and add auto-switch

- Rename DataverseSqlNotebookController → DataverseNotebookController
- Rename DataverseSqlNotebookSerializer → DataverseNotebookSerializer
- Rename registerDataverseSqlNotebooks → registerDataverseNotebooks
- Rename command newDataverseSqlNotebook → newDataverseNotebook
- Add auto-switch cell language based on content:
  - First char '<' → FetchXML mode
  - First char not '<' → SQL mode
  - Only triggers for cells < 30 chars (fresh cells)
- Update openQueryInNotebook to auto-detect SQL vs FetchXML
- Keep user-facing name as "Power Platform Developer Suite Notebook"
- Add visual builder implementation plan

* fix: resolve 5 bugs across multiple panels

Bug #1: Persistence Inspector text selection
- Move user-select: none from .tree-header to .tree-toggle only

Bug #2: Plugin Trace Viewer Ctrl+A shortcuts
- Add keyboard shortcut handlers with stopPropagation for inputs

Bug #3: Import Job Viewer clickable links
- Use CellLink pattern instead of HTML string in mapper
- VirtualTableRenderer expects solutionNameLink, not solutionNameHtml

Bug #4: Infinite loading spinner (5 panels)
- Replace scaffoldingBehavior.refresh with postMessage for data updates
- Move showTableLoading before data fetch

Bug #5: Data Explorer aliased lookup links
- Detect lookuplogicalname annotation on any key, not just _xxx_value

* fix(persistence-inspector): enable text selection for content elements

Add user-select: text to entry and tree view elements to allow mouse
selection and Ctrl+A within storage entries. Buttons remain unselectable
to prevent copying UI elements with content.

* fix(tests): add flushPromises helper for async panel handler tests

PanelCoordinator uses `void this.handleMessage()` which runs handlers
asynchronously without awaiting. Tests were failing because they
asserted before async operations completed.

Changes:
- Add flushPromises() helper to 4 test files
- Update message handler calls to not await (returns void)
- Add flushPromises() after handler calls to wait for async completion
- Add longer delays in WebResources race condition tests (150ms, 100ms)
  to wait for mock setTimeout delays to complete

Affected test files:
- PersistenceInspectorPanelComposed.integration.test.ts
- EnvironmentSetupPanelComposed.integration.test.ts
- WebResourcesPanelComposed.integration.test.ts
- MetadataBrowserPanel.integration.test.ts

* docs: clean up tracking docs, add aggregate/DISTINCT scope

- Delete completed tracking docs:
  - BUG_FIXES_2025_12_TODO.md (all 5 bugs fixed)
  - DATAVERSE_SQL_NOTEBOOKS_TODO.md (all issues resolved)
  - SAFE_WEBVIEW_PANEL_CANCELLATION_TODO.md (moved to tech debt)

- Add panel cancellation pattern to low-priority tech debt
  - Documents the pattern for future reference
  - Lists panels that could benefit from cancellation
  - WebResources implementation serves as reference

- Update INTELLISENSE_IMPROVEMENTS_TODO.md:
  - Mark Phase 3 (notebooks) as COMPLETED
  - Add detailed Phase 4 scope: DISTINCT, COUNT, SUM, AVG, MIN, MAX, GROUP BY
  - Add future phases for advanced features (HAVING, date grouping, exotic JOINs)
  - Document FetchXML link-types that have no SQL equivalent

* feat(sql): add DISTINCT, aggregate functions, and GROUP BY support

Add SQL features that have direct FetchXML equivalents:

Parser:
- DISTINCT keyword: SELECT DISTINCT name FROM account
- COUNT(*), COUNT(column), COUNT(DISTINCT column)
- SUM, AVG, MIN, MAX aggregate functions
- GROUP BY clause with multiple columns
- Aliases for aggregates: COUNT(*) AS total

Transpiler:
- DISTINCT → <fetch distinct="true">
- Aggregates → <fetch aggregate="true"> with appropriate aggregate type
- COUNT(*) uses entity primary key column (e.g., accountid)
- GROUP BY → groupby="true" on attribute elements
- Auto-generate aliases for aggregates without explicit alias

Fixes:
- Preserve original casing in lexer for keyword aliases
- COUNT(*) uses {entityname}id instead of invalid name="*"

Tests: 39 new unit tests (20 parser + 19 transpiler)

* feat(notebooks): add SQL/FetchXML toggle conversion and improve paste detection

Toggle button now converts query content when switching languages:
- SQL → FetchXML: Uses SqlParser + SqlToFetchXmlTranspiler
- FetchXML → SQL: Uses FetchXmlToSqlTranspiler with full aggregate support

FetchXmlToSqlTranspiler now properly handles:
- COUNT(*), COUNT(column), SUM, AVG, MIN, MAX aggregate functions
- COUNT(DISTINCT column) for distinct aggregates
- GROUP BY clause from groupby="true" attributes
- DISTINCT keyword from fetch distinct="true"

Paste auto-detection improved:
- Now detects paste anywhere in cell, not just empty cells
- Switches language based on pasted content's first character
- '<' triggers FetchXML, anything else triggers SQL (if in FetchXML mode)

* feat(sql): preserve comment positions during SQL/FetchXML round-trip

- Add trailing comment support for conditions (comparison, LIKE, NULL, IN)
- Fix parser to attach comments after commas in column/ORDER BY/GROUP BY lists
- Generate multi-line SQL output for better readability
- Associate XML comments with nearest preceding element by position
- Output inline comments on correct lines instead of dumping at top

SQL output now formatted as:
  -- Leading comment
  SELECT
    column1, -- comment
    column2
  FROM table
  WHERE condition = value -- inline comment

* fix(fetchxml): support ORDER BY alias in aggregate queries and XML comments

- FetchXmlValidator: Add context-aware order validation
  - Aggregate queries require 'alias', regular queries require 'attribute'
  - Add XML comment stripping to handle comments before <fetch>

- FetchXmlToSqlTranspiler: Parse and use 'alias' for ORDER BY
  - Update ParsedOrder interface to include optional alias field
  - Use alias in ORDER BY clause when present (aggregate queries)

- SqlToFetchXmlTranspiler: Generate alias for ORDER BY in aggregates
  - Detect when ORDER BY column matches a SELECT alias
  - Preserve alias case when generating <order alias="...">

Fixes validation error for Microsoft's documented aggregate FetchXML syntax.

* docs: adopt stabilization-first testing workflow

Change testing philosophy from per-layer tests during implementation
to tests after F5 validation. This reduces wasted effort when pivoting
and gets to manual testing faster.

Key changes:
- Phase 5: Implementation now "exploration mode" (no tests required)
- Phase 6: New "F5 Validation" phase for manual testing/iteration
- Phase 7: New "Stabilization & Tests" phase (required before PR)
- Coverage targets changed to guidelines (80%+ domain, 70%+ app)
- Tests still required before PR, just written after design is validated

* docs: consolidate tracking docs and update feature status

- Update DATA_MANAGEMENT.md: move IntelliSense, Notebooks, Aggregates,
  and basic JOINs to Implemented section; add Deferred section for
  advanced features (HAVING, date grouping, exotic JOINs)
- Delete INTELLISENSE_IMPROVEMENTS_TODO.md (completed)
- Simplify FINISH_FEATURES_TODO.md to reflect actual progress
- Update docs/future/README.md with current status

* feat(data-explorer): implement Visual Query Builder with entity selection

Visual Query Builder Step 2 implementation:
- Entity picker dropdown with grouped standard/custom entities
- Collapsible query preview section (FetchXML/SQL tabs)
- Results table with search, sorting, and record links
- Syntax highlighting using shared SqlHighlighter/XmlHighlighter

Domain layer:
- VisualQuery value object with column/filter/sort management
- QueryColumn, QueryCondition, QueryFilterGroup, QuerySort value objects
- FetchXmlOperator with comprehensive operator-to-FetchXML mapping
- FetchXmlGenerator and FetchXmlParser services

Bug fixes in this commit:
- Fixed entity selection sending null (message format mismatch)
- Fixed results table not rendering (missing message handlers)
- Fixed preview tab warnings (added data-custom-handler attribute)
- Eliminated syntax highlighting duplication via webpack bundling

* fix(panels): resolve loading state race condition showing "No data found" flash

- Add isLoading: true to scaffold refresh in all 6 data table panels
- Fix virtualTableSectionView to render loading row inside table structure
- Fix dataTableSectionView to render loading row inside table structure
- Add data-loading attribute for VirtualTableRenderer to detect loading state
- Update VirtualTableRenderer to skip initial render when loading
- Fix solutionFilterView to always render container for postMessage updates
- Update PANEL_INITIALIZATION_PATTERN.md with correct patterns

Affected panels: Import Jobs, Solutions, Web Resources, Environment Variables,
Connection References, Plugin Traces

* docs: add environment repository caching to technical debt

Track redundant EnvironmentRepository.getAll() calls during panel
initialization. 5+ calls happen within 100ms, each mapping all DTOs.
Low priority - fix when naturally touching EnvironmentRepository.

* refactor(notebook): simplify naming and add FetchXML example

- Rename command from "New Dataverse Notebook" to "New Notebook"
- Rename displayName from "Power Platform Developer Suite Notebook" to "Dataverse Notebook"
- Add FetchXML example cell to default notebook content (alongside SQL)
- Add tip about toggle button for SQL/FetchXML conversion

* fix(panels): add openMaker to LoadingStateBehavior config in all 6 panels

When scaffold renders with isLoading: true, ActionButtonsSection disables
ALL buttons in HTML. LoadingStateBehavior.setLoading(false) only re-enables
buttons in its config. Since openMaker was excluded, it stayed disabled.

Changes:
- Add openMaker to LoadingStateBehavior config in all 6 panels
- Fix SolutionExplorer showTableLoading to use updateVirtualTable command
- Add setLoading(true/false) wrapper in PluginTraceViewer initializeAndLoadData

Affected panels: Solutions, Import Jobs, Web Resources, Connection References,
Environment Variables, Plugin Traces

* feat(data-explorer): complete Visual Query Builder layout and UX improvements

- Implement two-pane scrollable layout with collapsible query builder section
- Fix columns not loading on panel restore (load attributes for restored entity)
- Fix Ctrl+A not working in search inputs (allow native behavior in text inputs)
- Persist and restore full query state (entity + selected columns)
- Use consistent search box pattern with emoji placeholder (🔍)
- Add ColumnOptionViewModel and mapper for column picker
- Update CSS for proper scrolling (max-height: 350px on query builder container)

* docs: update Visual Query Builder progress tracking

* feat(data-explorer): complete Filter Builder MVP with persistence and polish

Filter Builder Implementation:
- Add/remove filter conditions with field, operator, value inputs
- Operator dropdown varies by attribute type (text, number, date, lookup, etc.)
- Value input varies by type (text, number, datetime-local, boolean select)
- AND logic for all conditions (MVP scope)
- Filter persistence with entity and column state
- Filters appear in FetchXML/SQL preview in real-time
- Fix focus loss bug when typing in filter value inputs

Column Display & Ordering:
- Sort columns by logical name (not display name) for consistency
- Column picker: show "logicalName DisplayName Type" format
- Filter dropdown: show "logicalName (DisplayName)" format
- Update CSS to make logical name prominent (monospace font)
- Plugin Trace Viewer: sort filter fields by OData name

Bug Fixes:
- Filter out IsValidForRead=false columns to prevent query errors
- Virtual/computed columns like "isprivate" no longer cause API errors

Files added:
- FilterConditionViewModel.ts - ViewModel for filter row data
- FilterOperatorConfiguration.ts - Operators by attribute type

Files modified:
- DataExplorerPanelComposed.ts - Filter command handlers & persistence
- VisualQueryBuilderBehavior.js - Dynamic filter row rendering
- visualQueryBuilderView.ts - Server-side filter section HTML
- data-explorer.css - Filter section styling
- DataverseIntelliSenseMetadataRepository.ts - IsValidForRead filter
- ColumnOptionViewModelMapper.ts - Sort by logical name
- FilterField.ts - Sort Plugin Trace fields by OData name

* feat(data-explorer): complete Sort/Options sections + Cell Selection behavior

Visual Query Builder:
- Sort Section (3.4): attribute dropdown, direction toggle, clear button
- Query Options (3.5): Top N input (1-5000), Distinct checkbox
- Both sections collapsible with persistence and preview integration

Cell Selection (Excel-style):
- Created CellSelectionBehavior.js for cell-based rectangular selection
- Click to select, drag to range, Shift+click to extend
- Ctrl+A selects all cells, Ctrl+C copies as TSV
- Headers included in copy when entire table is selected
- Integrated with VirtualTableRenderer and DataTableBehavior
- Added to all 8 panels (works on 7, Data Explorer has timing issue)

Note: Data Explorer cell selection deferred - webpack bundle timing issue
with CellSelectionBehavior.js. Tracked in CELL_SELECTION_TODO.md.

* fix(plugin-traces): remove non-functional "Open in Maker" button

Plugin trace logs are not viewable in Maker Portal - they exist in
Admin Center or classic Dynamics. The button was incorrectly navigating
to the generic Maker home page which was not useful.

Removed:
- openMaker command type
- Button from toolbar (now just Refresh)
- Command handler and handleOpenMaker method
- LoadingStateBehavior config for the button

* fix(panels): fix environment reversion bug after switching and returning

The disposal handler was capturing the original environment ID at panel
creation time instead of using the current environment ID. When a user
switched environments within a panel, the disposal closure still had
the old ID, causing it to delete the wrong map entry and leave the new
environment's entry orphaned.

Added abstract getCurrentEnvironmentId() method to EnvironmentScopedPanel
that subclasses implement, allowing the disposal handler to use the
current environment ID at disposal time rather than the captured one.

Includes regression test that fails without fix and passes with fix.

* feat(data-explorer): add sticky Execute/Clear action bar to query builder

Add a sticky action bar at the bottom of the query builder section with
Execute and Clear buttons, always visible without scrolling.

- Add Execute button with loading spinner state and Ctrl+Enter shortcut
- Add Clear button that resets columns, filters, sort, options, results
  while preserving entity selection
- Move Execute from toolbar to action bar for better UX
- Style action bar with sticky positioning and VS Code theme colors

* docs: update progress tracking and defer features to future

Progress Updates:
- Mark Step 4 (Sticky Action Bar) as complete
- Mark Step 5 (Export/Import Toolbar) as in progress
- Reduce v0.3.0 scope to ~10-16 hours remaining

Deferred to v1.0+ (docs/future/DATA_MANAGEMENT.md):
- Query History (notebooks serve this purpose now)
- INSERT/UPDATE/DELETE
- View Management / UserQuery Save (needs layoutxml)
- Advanced VQB Features (AND/OR groups, Joins, Aggregates in VQB)

* docs: comprehensive changelog update for v0.3.0 and cleanup tracking docs

CHANGELOG additions:
- Data Explorer - Visual Query Builder (entity, columns, filters, sort, options)
- Data Explorer - Export/Import Toolbar (CSV, JSON, FetchXML, SQL, Notebook)
- Data Explorer - Notebook Integration (CodeLens, bidirectional workflow)
- Data Explorer - IntelliSense (SQL + FetchXML autocomplete)
- Data Explorer - Notebooks (.ppdsnb format)
- Data Explorer - Aggregates & JOINs (COUNT, GROUP BY, INNER/LEFT JOIN)
- Cell Selection (Excel-style) - all 8 panels

Deleted obsolete tracking docs:
- CELL_SELECTION_TODO.md (complete)
- DATA_EXPLORER_V03_REQUIREMENTS.md (superseded by FINISH_FEATURES_TODO.md)

* feat(data-explorer): add Export/Import toolbar with file export capabilities

- Move Execute/Clear buttons from sticky action bar to toolbar
- Add Export dropdown with Results (CSV, JSON) and Query (FetchXML, SQL, Notebook) options
- Add Import dropdown for FetchXML and SQL file import
- Import parses files and populates Visual Query Builder
- Fix file extension handling - ensure .csv, .json, .xml, .sql extensions are appended
- Fix notebook displayName consistency ("Power Platform Developer Suite Notebook")
- Remove old sticky action bar (actions now in toolbar)
- Reuse shared DropdownComponent for toolbar dropdowns

* fix(notebooks): rename Dataverse Notebook to Power Platform Developer Suite Notebook

Update all references to use the correct product name for consistency
with package.json displayName and other documentation.

* feat(notebooks): add bidirectional notebook-panel integration and cell export

Notebook → Panel Integration:
- Add "Open in Data Explorer" toolbar button for notebook code cells
- Parse cell query (SQL or FetchXML) and load into Visual Query Builder
- Environment from notebook metadata auto-selects panel environment

Notebook Cell Export:
- Add "Export Results to CSV" and "Export Results to JSON" in cell menu
- Store query results per cell after execution
- Reuse CsvExportService for file save dialog and export

Technical changes:
- DataExplorerPanelComposed: add loadQueryFromExternal() public method
- initializeDataExplorer: return panel instance for external interaction
- DataverseNotebookController: store results by cell URI, add export helpers
- package.json: new commands in notebook/cell/title menu

* refactor: remove pre-existing dead code from v0.2.0

Remove unused code that was created during the v0.2.0 Clean Architecture
refactor but never adopted:

HTML component helpers (never imported):
- button.ts, formField.ts, section.ts, select.ts
- Views use plain template literals instead of these abstractions

DataTablePanelCoordinator infrastructure (replaced by PanelCoordinator):
- DataTablePanelCoordinator.ts and its test
- IDataTablePanelCoordinator.ts interface
- DataTableBehaviorRegistry.ts and interface
- All panels use the newer PanelCoordinator pattern

Other dead code:
- pluginTraceToolbarView.ts - render function never imported
- isEnvironmentChangeMessage type guard - never called

* test(data-explorer): improve test coverage and document parser limitation

- Add 200+ tests across dataExplorer domain/application layers
- Exclude FetchXmlParser.ts and FetchXmlToSqlTranspiler.ts from coverage
  (regex-based parsing cannot handle nested XML - documented limitation)
- Document stack-based parser refactoring as scheduled technical debt
- All 289 test suites pass with 7,757 tests

Coverage improvements:
- SqlContextDetector: 79.7% → 95.94% stmts, 71.4% → 94.28% branches
- FetchXmlContextDetector: 87.5% → 92.18% branches
- IntelliSenseContextService: 69.6% → 100% stmts/branches
- SqlAst: 93.7% → 100% stmts/branches
- FetchXmlOperator: 75% → 100% branches
- QueryFilterGroup: 84.61% → 96.15% branches

Technical debt documented:
- docs/technical-debt/scheduled/PARSER_REFACTORING.md
- Solution: Stack-based tokenizer (zero dependencies)
- Timeline: Post v0.3.0 release

* refactor: remove remaining dead code helpers

Remove unused helper functions and files:
- ImportJobLinkView.ts - clickable link helpers never integrated
- SolutionLinkView.ts - clickable link helpers never integrated
- TypeGuards.ts - type guards never called (isTreeNodeArray, etc.)
- getInputTypeForAttribute - filter input helper never used

* docs: mark all v0.3.0 features complete

* docs: move Visual Query Builder to implemented in future planning

* refactor(data-explorer): extract coordinators from panel

Extract three coordinators from DataExplorerPanelComposed to separate
concerns and reduce file size (2182 → 1016 lines):

- DataExplorerMetadataLoader: entity/attribute loading and caching
- DataExplorerExportImportCoordinator: export/import file operations
- VisualQueryBuilderCoordinator: query state (columns, filters, sort)

Panel remains orchestrator, delegating via typed context interfaces.

* refactor(data-explorer): add eslint-disable justification for panel size

* docs: remove tracking docs (preserved in git history)

* chore(release): bump version to 0.3.0

Mark v0.3.0 release with all features complete:
- Web Resources with conflict detection
- Metadata Browser enhancements
- Data Explorer Visual Query Builder
- IntelliSense for SQL and FetchXML
- Aggregates & JOINs support
- Cell Selection (Excel-style)
- Notebook integration

* fix(deps): update jws to fix HMAC signature vulnerability

* fix(security): address CodeQL security findings

- Fix XSS vulnerabilities in VisualQueryBuilderBehavior.js:
  - Escape position text in showQueryError
  - Use DOM methods instead of innerHTML in updateQueryOptionsSummary
  - Validate boolean type for aria-selected attribute in updateColumnPicker
- Add origin verification to postMessage handler for VS Code webview security
- Fix incomplete XML comment sanitization in FetchXmlValidator.ts
  - Use iterative replacement to handle nested patterns
- Remove unused variable (searchInput) and function (clearColumnSearch)

* fix(security): escape position values individually for CodeQL

* test(data-explorer): add tests for IntelliSense value objects and use cases

Add comprehensive tests for:
- OperatorSuggestion value object (domain layer)
- ColumnOptionViewModelMapper (application mapper)
- GetFetchXmlElementSuggestionsUseCase
- GetOperatorSuggestionsUseCase
- IntelliSenseMetadataCache service

These tests address coverage threshold failures by achieving:
- 100% coverage for domain value objects (95% required)
- 100% coverage for application mappers and use cases (90% required)
- 87.5% branch coverage for cache service (85% required)

* test(coverage): add tests for Views and CompletionMappers

- Add tests for visualQueryBuilderView.ts (HTML generation)
- Add tests for all 4 CompletionMapper files (VS Code type mapping)
- Remove corner-cut exclusions from jest.config.js
- Coverage now legitimately meets thresholds:
  - Statements: 94.6% (threshold: 85%)
  - Branches: 91.1% (threshold: 80%)
  - Functions: 97.03% (threshold: 85%)
  - Lines: 94.61% (threshold: 85%)

* docs: restructure README for user focus

- Add Data Explorer and Web Resources to Key Features
- Add Quick Start, Settings, and Requirements sections
- Remove developer-focused content (architecture, test counts, coverage)
- Simplify installation (marketplace only)
- Add screenshots to technical debt for future work

Developer content already exists in CONTRIBUTING.md.
joshsmithxrm added a commit that referenced this pull request Mar 18, 2026
Solutions (#1,#2,#3,#5): Include Managed toggle, sort controls,
Visible/API Managed fields, Maker Portal button, isVisible/isApiManaged
end-to-end C# support.

Import Jobs (#7,#8,#9): Search bar, Operation Context column
(end-to-end C#→TS), record count with filtered status.

Plugin Traces (#11,#12,#17,#18,#55): CRITICAL Trace Level dropdown
fix, Maker Portal URL fix (Dynamics 365 classic), status text labels,
record count, search bar.

Web Resources (#19): Restored Created By and Created On columns.

Connection References (#23,#24,#25,#28,#55): Expandable flow/connection
detail with chevron toggle, ISO timestamp formatting, search bar,
status badge improvements (Unknown/Unbound), Sync Settings button.

Environment Variables (#29,#31,#55): Modified On column restored,
search bar, Sync Settings button.

Metadata Browser (#37): Custom Only filter toggle for entities.

Data Explorer (#41,#42): Clear button, Import button (file dialog).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Mar 19, 2026
Solutions (#1,#2,#3,#5): Include Managed toggle, sort controls,
Visible/API Managed fields, Maker Portal button, isVisible/isApiManaged
end-to-end C# support.

Import Jobs (#7,#8,#9): Search bar, Operation Context column
(end-to-end C#→TS), record count with filtered status.

Plugin Traces (#11,#12,#17,#18,#55): CRITICAL Trace Level dropdown
fix, Maker Portal URL fix (Dynamics 365 classic), status text labels,
record count, search bar.

Web Resources (#19): Restored Created By and Created On columns.

Connection References (#23,#24,#25,#28,#55): Expandable flow/connection
detail with chevron toggle, ISO timestamp formatting, search bar,
status badge improvements (Unknown/Unbound), Sync Settings button.

Environment Variables (#29,#31,#55): Modified On column restored,
search bar, Sync Settings button.

Metadata Browser (#37): Custom Only filter toggle for entities.

Data Explorer (#41,#42): Clear button, Import button (file dialog).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
joshsmithxrm added a commit that referenced this pull request Mar 19, 2026
* fix(cdp): use pwsh Expand-Archive for VSIX extraction on Windows

bsdtar interprets the C: drive prefix as a remote host, breaking
VSIX extraction in --vsix mode. Use PowerShell's Expand-Archive on
Windows; keep tar on other platforms.

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

* plan: extension UX audit fixes — 28 findings across 10 phases

Side-by-side comparison of legacy v0.3.4 vs new extension produced
55 findings. After triage: 28 fixes, 22 keep-new-behavior, 5 deferred.
Organized into 10 phases (1 cross-cutting + 9 per-panel) for parallel
agent execution.

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

* feat(ext): Phase 1 — cross-cutting infrastructure fixes

- Add Connection References + Environment Variables to sidebar Tools (#56, #57)
- Standardize command titles: "Open Data Explorer", "Open Plugin Traces" (#51)
- Remove text-transform: uppercase from 5 panel CSS files for Title Case headers (#10)

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

* feat(ext): Phases 2-9 — UX audit fixes across all 8 panels

Solutions (#1,#2,#3,#5): Include Managed toggle, sort controls,
Visible/API Managed fields, Maker Portal button, isVisible/isApiManaged
end-to-end C# support.

Import Jobs (#7,#8,#9): Search bar, Operation Context column
(end-to-end C#→TS), record count with filtered status.

Plugin Traces (#11,#12,#17,#18,#55): CRITICAL Trace Level dropdown
fix, Maker Portal URL fix (Dynamics 365 classic), status text labels,
record count, search bar.

Web Resources (#19): Restored Created By and Created On columns.

Connection References (#23,#24,#25,#28,#55): Expandable flow/connection
detail with chevron toggle, ISO timestamp formatting, search bar,
status badge improvements (Unknown/Unbound), Sync Settings button.

Environment Variables (#29,#31,#55): Modified On column restored,
search bar, Sync Settings button.

Metadata Browser (#37): Custom Only filter toggle for entities.

Data Explorer (#41,#42): Clear button, Import button (file dialog).

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

* fix(ext): review fixes — colSpan bug and command injection

- Connection References: fix colCount from wrong heuristic (8) to
  correct value (7) matching actual column count
- CDP tool: sanitize paths for PowerShell injection (escape single
  quotes); use execFileSync for tar on Unix to avoid shell interpretation

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

* style(ext): extract inline styles to CSS classes per Gemini review

Move search input and sort select inline styles to dedicated
.toolbar-search and .toolbar-select CSS classes across 4 panels
(Connection Refs, Env Variables, Import Jobs, Solutions).

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

* fix(ext): add missing webview entry points to knip config

The 6 non-query/solutions webview panels are esbuild entry points but
were missing from knip.json, causing false-positive unused-file reports.
Also un-export internal-only types from shared modules.

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

* fix(ext): solution filter GUID bug and raw ISO timestamps

- SolutionFilter shared component used uniqueName as option value
  instead of GUID id, causing "solutionId must be a valid GUID" error
  on Web Resources (and silently wrong on Conn Refs / Env Vars)
- Import Jobs and Web Resources rendered raw ISO timestamps; add
  formatDateTime helper matching Plugin Traces / Conn Refs pattern

Found by QA blind verification agents.

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

* fix(ext): review fixes — escaping, shell safety, URL normalization

- Solutions panel: escape rootComponentBehavior and boolean ternaries
  before innerHTML insertion (S1 compliance)
- Connection References: escape literal "Unbound" for consistent
  escaping discipline
- CDP tool: use execFileSync instead of execSync for PowerShell
  VSIX extraction (S2 compliance — no shell: true)
- Plugin Traces: strip trailing slash from environment URL before
  Maker Portal link construction

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

* fix(ext): escape formatDate output in solutions detail card

Wrap formatDate() calls in escapeHtml() for consistent escaping
discipline — formatDate can return raw ISO string on parse failure.

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

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant