Three new projects as a clean-slate V2 fork of the Legacy Agent:
AutopilotMonitor.Agent.V2 — net48 exe, minimal Program.cs,
buildcounter 2.0.N, version-v2.json
AutopilotMonitor.Agent.V2.Core — net48 library, 94 files copied from
Agent.Core via bulk sed namespace
rewrite; same folder layout
AutopilotMonitor.DecisionCore.Tests — xUnit net8.0 with ReplayHarness
+ 13 smoke/harness tests
V2 isolation is build-time-enforced via V2Isolation.targets imported from
both V2 csproj files — any Legacy ProjectReference fails the build with a
clear error. Grep-verified at commit time: zero `using
AutopilotMonitor.Agent.Core` statements and zero Legacy ProjectReferences
in the V2 tree.
Per plan §2.11, kernel items (CompletionStateMachine, CompletionGuards,
EnrollmentTracker*, Flows/*, WhiteGloveClassifier, WhiteGloveSignals,
EnrollmentStatePersistence) are transitionally retained so the V2 tree
compiles; M4 removes them when SignalAdapters + V2Orchestrator take over.
Per user direction (feedback_v2_kernel_only_refactor): the V2 refactor
replaces only the decision kernel. All peripheral capabilities — gather
rules, analyzers, diagnostics upload, timezone, server-driven actions,
summary dialog launch, env-var resolution, version checks, registry
watchers, network/DO/performance telemetry, self-update, bootstrap→cert
handover, self-destruct — are preserved verbatim via the bulk copy.
Supporting M3 bring-up platform:
- ReplayHarness (empty-stream deterministic, SHA256 hash over terminal
state fields) in DecisionCore.Tests/Harness/
- Fixture scaffold under tests/fixtures/: committed anonymized directory
with commit-policy README, plus gitignored enrollment-sessions-local/
for raw exports
- tools/export-session-fixture.mjs with --help / --dry-run / --validate
modes; real MCP wiring marked TODO(v2-m3)
V2 bootstrap scripts scripts/Bootstrap/Install-AutopilotMonitor-v2(.|-dev).ps1
(committed, pure ASCII verified per feedback_ps1_ascii_only). V2 deployment
scripts under scripts/Deployment/V2/ are gitignored (analog to Legacy).
Test totals at M2 gate: 13 DecisionCore + 507 Agent.Core (unchanged) +
557 Functions (unchanged) = 1077 green.
Plan: plans/REFACTOR_AGENT_V2.md §4 M2 + §2.16 V2-Agent-Split.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New netstandard2.0 project src/Shared/AutopilotMonitor.DecisionCore/ with
14 scaffolding types across Signals/, State/, Classifiers/, Engine/.
Agent.Core and Functions reference the library without call-sites; the
full solution builds 0 errors, 0 warnings. DecisionEngine.Reduce is an
intentional NotImplementedException stub — M3 fills in the partial-class
reducer.
Invariants wired into the scaffolding:
- Immutable DTOs (sealed + get-only + With-methods) per L.3
- Pflicht-Evidence validation in Evidence ctor per L.5
- KindSchemaVersion enforcement per L.6
- AssemblyVersion 2.0.0.0 as ReducerVersion source per §2.10
Architecture principles L.1–L.18 extracted to
.claude/architecture-principles.md as persistent Claude-session context.
Plan: plans/REFACTOR_AGENT_V2.md §4 M1. Zero runtime risk.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WhiteGlove (Pre-Provisioning) sessions were incorrectly classified as
self-deploying because OnDeviceSetupProvisioningComplete and the esp_exiting
handler both race ahead of the signal-correlated WhiteGlove detector (30s
timer + 10min stability window). Two WhiteGlove signals existed but were
never consumed by completion logic:
1. EventID 509 (whiteglove_started) — already detected by
ModernDeploymentTracker but not exposed to EnrollmentTracker
2. SaveWhiteGloveSuccessResult=succeeded in DeviceSetup registry JSON —
present in esp_provisioning_raw but invisible to ParseSubcategories
(no *Subcategory suffix)
Adds WhiteGlove guards at both device-only completion paths:
- OnDeviceSetupProvisioningComplete (registry polling path)
- OnFinalizingSetupPhaseTriggered esp_exiting + SkipUserStatusPage path
Exposes IsWhiteGloveStartDetected and HasSaveWhiteGloveSuccessResult
through EspAndHelloTracker. Mirrors guards in CompletionStateMachine.
Backend safety net: classifies whiteglove_started events and sets
IsPreProvisioned=true early as fallback for older agents.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enrich EventTypeIndex with MaxSeverity/Sources for server-side pre-filtering,
add GetSessionEventsByTypeAsync for OData-filtered event fetch (eliminates N+1),
and new /api/raw/events/search endpoint for MCP search tool pre-filtering.
- EventTypeIndex now stores MaxSeverity, MaxSeverityName, Sources per session-eventType
- GetSessionEventsByTypeAsync: OData filter on EventType within a session partition
- SearchEventsByTypesAsync: combines index lookup + filtered fetch across sessions
- SearchEventsFunction: GET /api/raw/events/search + global variant
- QueryRawEventsFunction: uses filtered fetch instead of full partition scan
- Routes registered in EndpointAccessPolicyCatalog (MemberRead + GlobalAdminOnly)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Track MCP tool invocations in App Insights and UserUsageLog:
- Add ClientSource + McpToolName custom dimensions to RequestTelemetry
- Propagate tool name via X-MCP-Tool-Name header from MCP server
- Wrap all 26 tool handlers with withToolTelemetry for context propagation
- Add MCP_TOOL_LOGGING env var (default false) for optional stderr logging
- Add toolLoggingEnabled param to Bicep template for persistence
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gate WelcomeMessage on !loading so it only appears when sessions are
truly empty, not while the initial fetch is still in progress.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When search is active with <8 local results, automatically loads all
remaining sessions progressively (batch by batch) so the local search
can find matches across ALL fields (country, city, model, etc.).
Bottom button shows "Search all sessions..." with progress spinner
when search is active, keeps "Load 100 more..." for manual browsing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Part 5 of 5 in Monitoring/ bounded-context restructure. StallProbeCollector
lands in Enrollment/SystemSignals/. Empty Core/Tracking/Collectors/Network/
Analyzers/Flows/Replay/ directories removed. No behavior change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Part 3 of 5 in Monitoring/ bounded-context restructure. Split by purpose
(periodic metrics, hardcoded analyzers, backend-driven gather rules,
device info). Pure folder move + namespace update; no behavior change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Part 2 of 5 in Monitoring/ bounded-context restructure. Network/* plus
Core/EventSpool + Core/EventUploadOrchestrator moved into Monitoring/Transport/.
Pure folder move + namespace update; no behavior change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Part 1 of 5 in Monitoring/ bounded-context restructure. Moves Monitoring/Core/*
(minus EventSpool/EventUploadOrchestrator/DeviceInfoProvider/EnrollmentCompletionHandler
which belong to later PRs) into Monitoring/Runtime/. Interop/ stays on
Monitoring root. Pure folder move + namespace update; no behavior change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>