diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 37e0c216..7e12f90f 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -4,21 +4,57 @@ - **Use subagents liberally** for research, exploration, and parallel analysis — one focus each — to keep the main context clean. - **Verify before claiming done.** Run the tests, check the logs, show the evidence. Diff against `main` where behaviour could regress. - **Fix bugs autonomously.** Given a report, a failing test, or an error, resolve it — no hand-holding. -- **Capture corrections.** After any correction from the user, record the pattern and a preventing rule in `tasks/lessons.md`; review it at session start. +- **Capture corrections.** After any correction from the user, add a lesson to `internal/work/lessons.md` and update the rule block at its top. Read that rule block at session start. - Read files over 500 LOC in chunks. Never treat one grep as proof of absence. Codex reviews your output once you are done. +## Where knowledge lives + +| Content | Location | Rule | +|---|---|---| +| Customer documentation | separate repo `autopilotmonitor-docs` (GitBook; baked into the MCP `search_docs` corpus) | Any change ⇒ MCP redeploy. Commit in that repo (`cd` first). | +| Technical concept docs (OKF bundle) | `internal/` — private submodule, entry point `internal/docs/index.md` | Read the index first. Concept docs only for invariants, mechanisms and architecture a later change could silently break. | +| Decisions, including "we will not build X" | `internal/decisions.md` | One entry per decision: date, decision, why, applies-to, status. A concept doc only when a mechanism needs explaining. | +| Working files | `internal/work/` | See the next section. | +| Agent review criteria | `internal/docs/agent/architecture-principles.md` | Check every agent change against it. | +| Private operator instructions | `internal/CLAUDE.md` | Imported at the end of this file. Absent for contributors without submodule access; nothing in it may be copied into this public repo. | +| Infrastructure | `infra/` — private submodule | | +| Skills | `.claude/commands/` — private submodule | | +| Claude auto-memory | outside the repo, per machine | Private notes only. Anything the project must keep goes into `internal/`. | + +## Working files (`internal/work/`) + +- `todo.md` — the running task only: checkable steps plus a Review section. Cleared when the next task starts. +- `plans/.md` — one file per larger piece of work. The first line carries the status (AKTIV / RELEASED / VERWORFEN); the file ends with a `## Offen` section. +- `backlog.md` — the one backlog: an "Ideen" section for raw ideas at the top, then deferred feature pieces, open questions, tech debt, user actions and the deploy/verify long tail. One line per item with what is missing, the source plan and the date. Items are deleted when done or when they get a plan file, never ticked. +- `archive/` — closed plans whose review is worth keeping. +- `lessons.md` — corrections from the user; rule block at the top, narrative below. + +When → do: +- A plan is approved → copy it to `plans/.md`, put the steps into `todo.md`. +- A task closes → review into the plan file, leftovers as one-liners into `backlog.md`, clear `todo.md`. The commit message is the log. +- A backlog item is picked up → back into a plan file, removed from `backlog.md`. +- A decision is made, including a deliberate non-decision → entry in `internal/decisions.md`. +- Working files are committed inside `internal/` when a task closes, not on every tick. + +## Hard rules + +- Agent projects stay on .NET Framework 4.8. +- .NET build warnings are errors; only the NU1901–NU1904 advisories remain warnings. +- Never put real customer domains, tenant names or tenant IDs into code, tests, commits, comments or public docs. +- Deploy order is Backend → Web → MCP. Backend deploys are `workflow_dispatch` only. Verify the deployed version before claiming anything is live. +- Submodules (`internal/`, `infra/`, `.claude/commands/`): commit inside the submodule first, then bump the gitlink here. +- Stage explicit file lists; never `git add -A` or a directory. Pushing is the user's call. +- New API responses need a typed DTO plus the parity fact. MCP vocabularies are generated from the wire types, never retyped. +- Every route belongs in the route policy catalog; every new event type goes into the MCP resource catalog. + ## Code Quality - Simplicity first: minimal, targeted changes. No temporary fixes — find the root cause. - Where architecture is flawed, state is duplicated, or patterns are inconsistent, propose and implement the structural fix. Ask what a perfectionist reviewer would reject, and fix that too. - On non-trivial changes, ask whether there is a more elegant way before presenting. Skip it for simple fixes — don't over-engineer. -## Task Management - -Keep the plan in `tasks/todo.md` as checkable items, confirm it before implementing, tick items off as you go, and add a review section when done. - ## Customer-Facing Claims `src/Web/autopilot-monitor-web/app/{about,terms,privacy}/page.tsx` and `autopilotmonitor-docs/trust/*` state facts customers and security reviewers rely on. They drift silently. @@ -28,11 +64,18 @@ Keep the plan in `tasks/todo.md` as checkable items, confirm it before implement - Describe only what customers can actually use; operator-only infrastructure is not a feature. - Trust pages: durable phrasing over exact figures, and bump their "Last reviewed" date. -## Technical Docs — OKF Bundle (`docs/`, private submodule) +## Technical Docs — OKF Bundle (`internal/`, private submodule) -Contributor/AI-facing docs (customer docs live in the `autopilotmonitor-docs` repo). `docs/` is a **private** submodule (`okieselbach/Autopilot-Monitor-docs-internal`) — this repo is public, the docs are not. Start at `docs/index.md` before opening individual files. +Contributor/AI-facing docs (customer docs live in the `autopilotmonitor-docs` repo). `internal/` is a **private** submodule (`okieselbach/Autopilot-Monitor-internal`) — this repo is public, the bundle is not. Start at `internal/docs/index.md` before opening individual files. -- Write a concept doc only for durable knowledge a later change could silently break: invariants, architecture decisions, non-obvious mechanisms — not for every feature. YAML frontmatter: `type` (mandatory), plus `title`, `description`, `resource`, `tags`, `timestamp`. -- Register it in `docs/index.md`. There is no `log.md` — the commit message is the log. `index.md` is a reserved name. -- Commit inside the submodule first, then bump the gitlink here (same rule as `.claude/commands` and the private `infra/` submodule, `okieselbach/Autopilot-Monitor-infra`). +- Write a concept doc only for durable knowledge a later change could silently break: invariants, architecture decisions, non-obvious mechanisms — not for every feature. YAML frontmatter: `type` (mandatory, one of `Concept`, `Reference`, `Guide`), plus `title`, `description`, `resource`, `tags`, `timestamp`. +- Register it in `internal/docs/index.md`. There is no `log.md` — the commit message is the log. `index.md` is a reserved name. +- `internal/work/`, `internal/decisions.md` and `internal/CLAUDE.md` are not part of the bundle and are not listed in the index. - English, structural markdown (`# Schema`, `# Examples`, `# Citations`). Links between docs are RELATIVE — never `/`-prefixed, that breaks GitHub navigation. + +## Language + +- English for knowledge: concept docs, decisions, both CLAUDE files, code comments. +- German is fine for working files under `internal/work/`. + +Private half of these instructions (skills, private repositories, operations): @../internal/CLAUDE.md diff --git a/.claude/architecture-principles.md b/.claude/architecture-principles.md deleted file mode 100644 index 5971a2c0..00000000 --- a/.claude/architecture-principles.md +++ /dev/null @@ -1,136 +0,0 @@ -# Autopilot-Monitor — Agent Architecture Principles - -The principles are **not nice-to-haves**, they are review criteria: any code -change that violates a principle is either (a) a bug, (b) a reason to change the principle -(with user sign-off), or (c) an explicitly documented exception with rationale. - ---- - -## L.1 Truth Hierarchy (immutable) - -`SignalLog` (input) → `Journal` (decisions) → `Snapshot` (cache) → `Projections` (derivable). -No projection patches backwards into the journal or the signal log. On inconsistency, the -lower layer always wins (e.g. discard the snapshot, do not "repair" the signal log). - -## L.2 Event Sourcing as Foundation - -`SignalLog` is the only input truth. The reducer is pure: -`(oldState, signal) → (newState, transition, effects)`. The backend can re-derive at any -time from `SignalLog`. Replay yields the same `Journal` content. - -## L.3 Immutable State - -All DTOs in the decision core are `sealed` with get-only properties. No in-place mutation. -"Change" = new instance via `With…` method. This is the difference between "purely testable" -and "subtle heisenbugs". - -## L.4 Hypothesis Model instead of Flow Plugins - -Fuzziness is constitutive (White-Glove, enrollment type, device-only). A single reducer with -hypothesis fields (`Unknown/Weak/Strong/Confirmed/Rejected`), organized by scenario in partial -classes. **No** plugin runtime, because clean flow boundaries do not match reality. - -## L.5 Evidence Determinism - -Signal-log determinism is guaranteed: same log → same outcome. Every signal carries an -`Evidence` record with `Kind` (Raw / Derived / Synthetic) and mandatory fields. A signal -without evidence = adapter rejection = bug. - -## L.6 Signal Schema Versioning - -Every `DecisionSignalKind` has a `SchemaVersion`. The reducer dispatches on -`(Kind, SchemaVersion)` — old versions stay replay-capable. A new version or a new kind -without a replay fixture in `tests/fixtures/signal-kinds/{kind}-v{n}.json` = merge block. - -## L.7 Timer Monopoly - -Only the Deadline Scheduler (the EffectRunner role) holds decision-relevant timers. Collectors, -signal adapters and the orchestrator must not. `Task.Delay` or `new Timer(...)` in those -layers with session-state impact = merge block. `IClock` interface + virtual clock for -testability. - -## L.8 Classifier as Post-Hook Kernel Service - -`IClassifier` interface, swappable. The `ClassifierVerdict` flows back into the log as a -synthetic `ClassifierVerdictIssued` signal. `InputHash` (SHA256 over classifier-relevant -snapshot fields) is the anti-loop guard. Classifiers are not baked into the state machine. - -## L.9 Clean-Agent Principle on Refactors - -For structural refactors: build the new project in parallel to the legacy one, do not flag- -route inside the same process. Strict separation rule: no direct reference to legacy -projects. Code is copied, not shared. Legacy runs out, then gets removed. - -## L.10 Generic Telemetry Transport - -One spool for all telemetry types (events, signals, decision transitions). `TelemetryItemId` -is the type-agnostic upload cursor; the type-specific counters (`Event.Sequence`, -`SignalOrdinal`, `StepIndex`) remain storage / UI / reducer semantics. Drain guarantee: -"coordinated + idempotent + resumable" — **not** cross-table atomic, which is not achievable -with three separate tables anyway. - -## L.11 Separation: Agent Lifecycle vs Session State - -`DecisionState` is session-pure. Agent-process flags (crash, admin actions, boot time, -heartbeat status) live separately in `agent-lifecycle.json`, managed by the orchestrator, -never by the reducer. Prevents replay dilution by lifecycle events. - -## L.12 Flush-on-Append Persistence - -No batching of append operations. `FileOptions.WriteThrough` plus an explicit -`FlushAsync(flushToDisk: true)` per append. Every successful `Append` return means: on disk. -Durability > performance in the crash-prone OOBE context. - -## L.13 UI Primacy — End-Users vs Dev Tooling - -Product views (EventTimeline, PhaseTimeline) stay slim and stable. Debug / analysis tools -(Inspector with DecisionGraph, SignalStream, VerifierReport) live on their own subpage behind -an `adminMode` gate. The session-detail page does not get overloaded with dev components. - -## L.14 Forward Compatibility by Default - -Enums via `StringEnumConverter` + `UnknownFallbackEnumConverter` (unknown values → default, -never crash). New schema fields are nullable. The `ReducerVersion` stamp per journal row -allows older backends to read newer rows. Deletions only after a major version bump with -user sign-off. - -## L.15 Test Discipline - -Flow / scenario tests are prioritized over structural tests. Coverage targets per component -(DecisionCore ≥95 %, classifier 100 %, backend functions ≥85 %). A missing fixture for a -scenario = merge block. CI threshold check is a build failure, not a warning. - -## L.16 Fail-Safe Reducer Exceptions - -Exception in the reducer → `DecisionTransition` with `DeadEndReason=reducer_exception`, state -unchanged (fail-safe, never destroy state). Signal counts as processed (no retry loop). After -five consecutive exceptions → the orchestrator emits -`enrollment_failed(reason=reducer_instability)`. - -## L.17 Effect Error Handling by Class - -Three effect classes with their own strategy: - -- **Transient** (retry with exponential backoff 100 ms / 400 ms / 1600 ms): - `EmitEventTimelineEntry`, `PersistSnapshot` -- **Critical** (session abort, e.g. on timer-register failure): `ScheduleDeadline`, - `CancelDeadline` -- **Optional** (best-effort, classifier exception → `Inconclusive` verdict, no abort): - `RunClassifier` - -Every effect failure is logged as a `DecisionTransition`. - -## L.18 Implementation Discipline - -- **R1** Pre-flight plan check before every work step -- **R2** Delegate self-contained sub-tasks **and exploration** to subagents (Anthropic - recommendation: preserve main-context window on large refactors — quality assurance) -- **R3** Real verification (DB round-trip, index dual-write, agent signal emission) — no - "it compiles and runs" -- **R4** The plan is authority — deviations require user sign-off -- **R5** Out-of-scope items land in `tasks/todo.md`, not in memory -- **R6** High test coverage is a prerequisite for future refactorability, not a nice-to-have -- **R7** Code-structure discipline: small files (guideline ≤300 LoC), clear folders, partial - classes by scenario, check in with the user on any uncertainty (placement, naming, scope) - ---- diff --git a/.claude/commands b/.claude/commands index 1d28c43c..40ae3c35 160000 --- a/.claude/commands +++ b/.claude/commands @@ -1 +1 @@ -Subproject commit 1d28c43c5b577099ac957864d17c5f91128e0b0e +Subproject commit 40ae3c358144e2fdf8ff1a7e1819d555282ffec1 diff --git a/.github/scripts/Request-BuildNumber.ps1 b/.github/scripts/Request-BuildNumber.ps1 index 76f2803e..1b2fa652 100644 --- a/.github/scripts/Request-BuildNumber.ps1 +++ b/.github/scripts/Request-BuildNumber.ps1 @@ -65,7 +65,7 @@ function Read-Counter { $resp = Invoke-WebRequest -Uri $CounterUrl -Method Get -UseBasicParsing } catch { if ((Get-HttpStatus $_) -eq 404) { - throw "Counter blob not found at $CounterUrl. Seed it once with the last used build number: PUT the plain integer with 'x-ms-blob-type: BlockBlob' and 'If-None-Match: *'. See docs/versioning.md." + throw "Counter blob not found at $CounterUrl. Seed it once with the last used build number: PUT the plain integer with 'x-ms-blob-type: BlockBlob' and 'If-None-Match: *'. See internal/docs/versioning.md." } throw } diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f82b1170..7768bbf1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,13 +8,13 @@ on: push: branches: [main] paths-ignore: - - 'docs/**' + - 'internal/**' - '**/*.md' - 'LICENSE' pull_request: branches: [main] paths-ignore: - - 'docs/**' + - 'internal/**' - '**/*.md' - 'LICENSE' schedule: diff --git a/.gitignore b/.gitignore index 10ed73ff..d385e6d9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ bld/ [Ll]ogs/ # Build counter files: the authoritative counter is the shared blob -# (agent container, buildcounter-v{N}.txt, ETag-CAS — see docs/agent/build-counter-blob.md). +# (agent container, buildcounter-v{N}.txt, ETag-CAS — see internal/docs/agent/build-counter-blob.md). # The local file is only an offline fallback for -SkipUpload/bare-dotnet smoke builds. buildcounter.txt @@ -134,7 +134,6 @@ tests/fixtures/enrollment-sessions-local/ TODO.txt tools/orphan-analysis.py tools/export-session-fixture.mjs -tasks/ # Azure Table cleanup backups (dry-run exports + delete manifests) # Produced by /cleanup-table skill — never commit deletion payloads @@ -148,8 +147,8 @@ plans/REFACTOR_AGENT_V2.md # (storage account name, resource group are operator-specific) so it stays # out of the repo. Each operator keeps their own copy. scripts/Backup/setup-backup-container.ps1 -docs/Introduction-AutopilotMonitor.pptx -docs/~$Introduction-AutopilotMonitor.pptx +internal/docs/Introduction-AutopilotMonitor.pptx +internal/docs/~$Introduction-AutopilotMonitor.pptx # Playwright MCP browser artifacts (snapshots, screenshots, console logs) .playwright-mcp/ @@ -159,7 +158,6 @@ docs/~$Introduction-AutopilotMonitor.pptx src/Web/autopilot-monitor-web/public/version.json -# Local IME binaries scratch used by the /ime-decompile skill (MSI + msiexec- -# extracted payload per version, for grepping in binaries). Decompilates live in -# the private ime-decompiles repo, MSIs in the ime-archive blob - this stays local. +# Local IME installer scratch (MSI + extracted payload per version, for grepping +# in binaries). Operator-only, never committed. ime-files/ diff --git a/.gitmodules b/.gitmodules index eb50bf96..d22cfa05 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,8 +2,8 @@ path = .claude/commands url = https://github.com/okieselbach/Autopilot-Monitor-dotclaude.git [submodule "docs"] - path = docs - url = https://github.com/okieselbach/Autopilot-Monitor-docs-internal.git + path = internal + url = https://github.com/okieselbach/Autopilot-Monitor-internal.git [submodule "infra"] path = infra url = https://github.com/okieselbach/Autopilot-Monitor-infra.git diff --git a/docs b/docs deleted file mode 160000 index dd053d10..00000000 --- a/docs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dd053d1068afffd666e8c2b653b670d005f4c59e diff --git a/internal b/internal new file mode 160000 index 00000000..aa32b61c --- /dev/null +++ b/internal @@ -0,0 +1 @@ +Subproject commit aa32b61c50093f10bd818af9d74ddfaf15aaa584 diff --git a/rules/analyze/ANALYZE-DEV-007.json b/rules/analyze/ANALYZE-DEV-007.json index 46e87cad..9d2027af 100644 --- a/rules/analyze/ANALYZE-DEV-007.json +++ b/rules/analyze/ANALYZE-DEV-007.json @@ -2,7 +2,7 @@ "$schema": "../schema/analyze-rule.schema.json", "ruleId": "ANALYZE-DEV-007", "title": "System Clock Skew — TPM Attestation and ESP Timeout Risk", - "description": "The device's real-time clock deviates from NTP by more than two minutes. Microsoft documents that a clock off by several minutes causes TPM attestation errors (self-deploying/pre-provisioning) and ESP timeouts. Knowledge source: docs/agent/autopilot-ztd-diagnostics.md.", + "description": "The device's real-time clock deviates from NTP by more than two minutes. Microsoft documents that a clock off by several minutes causes TPM attestation errors (self-deploying/pre-provisioning) and ESP timeouts.", "severity": "warning", "category": "device", "version": "1.1.0", diff --git a/rules/analyze/ANALYZE-ENRL-003.json b/rules/analyze/ANALYZE-ENRL-003.json index ccd69951..6b420199 100644 --- a/rules/analyze/ANALYZE-ENRL-003.json +++ b/rules/analyze/ANALYZE-ENRL-003.json @@ -2,7 +2,7 @@ "$schema": "../schema/analyze-rule.schema.json", "ruleId": "ANALYZE-ENRL-003", "title": "TPM Attestation Failure — Known Error Code", - "description": "A TPM-attestation-related error code documented in the Microsoft Autopilot known-issues list was observed (0x800705B4, 0x801C03EA, 0x81039001, 0x81039023, 0x81039024, 0x80070490). These block self-deploying and pre-provisioning deployments during 'Securing your hardware'. Observability: attestation precedes MDM enrollment, so in the normal deployment model (agent installed via IME after enrollment) these codes are rarely visible — the rule primarily serves bootstrap-token deployments. See docs/agent/autopilot-ztd-diagnostics.md (Observability section).", + "description": "A TPM-attestation-related error code documented in the Microsoft Autopilot known-issues list was observed (0x800705B4, 0x801C03EA, 0x81039001, 0x81039023, 0x81039024, 0x80070490). These block self-deploying and pre-provisioning deployments during 'Securing your hardware'. Observability: attestation precedes MDM enrollment, so in the normal deployment model (agent installed via IME after enrollment) these codes are rarely visible — the rule primarily serves bootstrap-token deployments.", "severity": "high", "category": "enrollment", "version": "1.1.0", diff --git a/rules/analyze/ANALYZE-ENRL-004.json b/rules/analyze/ANALYZE-ENRL-004.json index b9c2fe6d..c1c84fd0 100644 --- a/rules/analyze/ANALYZE-ENRL-004.json +++ b/rules/analyze/ANALYZE-ENRL-004.json @@ -2,7 +2,7 @@ "$schema": "../schema/analyze-rule.schema.json", "ruleId": "ANALYZE-ENRL-004", "title": "MDM Enrollment Blocked — Known Error Code", - "description": "An enrollment-blocking error code documented in the Microsoft Autopilot known-issues/troubleshooting pages was observed (0x80180014, 0x80180018, 0xC1036501, 0x801C03F3, 0x80070774). Each has a specific, documented cause and fix. Observability: a blocked MDM enrollment normally means no agent gets installed at all (IME install happens after enrollment) — this rule can realistically only fire for bootstrap-token deployments (pre-MDM reporting) or mixed retry scenarios. See docs/agent/autopilot-ztd-diagnostics.md (Observability section).", + "description": "An enrollment-blocking error code documented in the Microsoft Autopilot known-issues/troubleshooting pages was observed (0x80180014, 0x80180018, 0xC1036501, 0x801C03F3, 0x80070774). Each has a specific, documented cause and fix. Observability: a blocked MDM enrollment normally means no agent gets installed at all (IME install happens after enrollment) — this rule can realistically only fire for bootstrap-token deployments (pre-MDM reporting) or mixed retry scenarios.", "severity": "high", "category": "enrollment", "version": "1.1.0", diff --git a/rules/analyze/ANALYZE-ENRL-005.json b/rules/analyze/ANALYZE-ENRL-005.json index a715e9c6..cec430de 100644 --- a/rules/analyze/ANALYZE-ENRL-005.json +++ b/rules/analyze/ANALYZE-ENRL-005.json @@ -2,7 +2,7 @@ "$schema": "../schema/analyze-rule.schema.json", "ruleId": "ANALYZE-ENRL-005", "title": "Hybrid Join Timeout 0x80004005 — Fixed by Windows Update", - "description": "A Microsoft Entra hybrid join Autopilot deployment hit error 0x80004005 — a documented build-dependent known issue, resolved by KB5065789 (25H2, build >= 26200.6725), KB5065426 (24H2, build >= 26100.6584), and KB5070312 (23H2, build >= 22631.6276). Knowledge source: docs/agent/autopilot-ztd-diagnostics.md (error-code map).", + "description": "A Microsoft Entra hybrid join Autopilot deployment hit error 0x80004005 — a documented build-dependent known issue, resolved by KB5065789 (25H2, build >= 26200.6725), KB5065426 (24H2, build >= 26100.6584), and KB5070312 (23H2, build >= 22631.6276).", "severity": "high", "category": "enrollment", "version": "1.1.0", diff --git a/rules/dist/analyze-rules.json b/rules/dist/analyze-rules.json index 055b0b57..3278ce58 100644 --- a/rules/dist/analyze-rules.json +++ b/rules/dist/analyze-rules.json @@ -1541,7 +1541,7 @@ { "ruleId": "ANALYZE-DEV-007", "title": "System Clock Skew — TPM Attestation and ESP Timeout Risk", - "description": "The device's real-time clock deviates from NTP by more than two minutes. Microsoft documents that a clock off by several minutes causes TPM attestation errors (self-deploying/pre-provisioning) and ESP timeouts. Knowledge source: docs/agent/autopilot-ztd-diagnostics.md.", + "description": "The device's real-time clock deviates from NTP by more than two minutes. Microsoft documents that a clock off by several minutes causes TPM attestation errors (self-deploying/pre-provisioning) and ESP timeouts.", "severity": "warning", "category": "device", "version": "1.1.0", @@ -1987,7 +1987,7 @@ { "ruleId": "ANALYZE-ENRL-003", "title": "TPM Attestation Failure — Known Error Code", - "description": "A TPM-attestation-related error code documented in the Microsoft Autopilot known-issues list was observed (0x800705B4, 0x801C03EA, 0x81039001, 0x81039023, 0x81039024, 0x80070490). These block self-deploying and pre-provisioning deployments during 'Securing your hardware'. Observability: attestation precedes MDM enrollment, so in the normal deployment model (agent installed via IME after enrollment) these codes are rarely visible — the rule primarily serves bootstrap-token deployments. See docs/agent/autopilot-ztd-diagnostics.md (Observability section).", + "description": "A TPM-attestation-related error code documented in the Microsoft Autopilot known-issues list was observed (0x800705B4, 0x801C03EA, 0x81039001, 0x81039023, 0x81039024, 0x80070490). These block self-deploying and pre-provisioning deployments during 'Securing your hardware'. Observability: attestation precedes MDM enrollment, so in the normal deployment model (agent installed via IME after enrollment) these codes are rarely visible — the rule primarily serves bootstrap-token deployments.", "severity": "high", "category": "enrollment", "version": "1.1.0", @@ -2077,7 +2077,7 @@ { "ruleId": "ANALYZE-ENRL-004", "title": "MDM Enrollment Blocked — Known Error Code", - "description": "An enrollment-blocking error code documented in the Microsoft Autopilot known-issues/troubleshooting pages was observed (0x80180014, 0x80180018, 0xC1036501, 0x801C03F3, 0x80070774). Each has a specific, documented cause and fix. Observability: a blocked MDM enrollment normally means no agent gets installed at all (IME install happens after enrollment) — this rule can realistically only fire for bootstrap-token deployments (pre-MDM reporting) or mixed retry scenarios. See docs/agent/autopilot-ztd-diagnostics.md (Observability section).", + "description": "An enrollment-blocking error code documented in the Microsoft Autopilot known-issues/troubleshooting pages was observed (0x80180014, 0x80180018, 0xC1036501, 0x801C03F3, 0x80070774). Each has a specific, documented cause and fix. Observability: a blocked MDM enrollment normally means no agent gets installed at all (IME install happens after enrollment) — this rule can realistically only fire for bootstrap-token deployments (pre-MDM reporting) or mixed retry scenarios.", "severity": "high", "category": "enrollment", "version": "1.1.0", @@ -2164,7 +2164,7 @@ { "ruleId": "ANALYZE-ENRL-005", "title": "Hybrid Join Timeout 0x80004005 — Fixed by Windows Update", - "description": "A Microsoft Entra hybrid join Autopilot deployment hit error 0x80004005 — a documented build-dependent known issue, resolved by KB5065789 (25H2, build >= 26200.6725), KB5065426 (24H2, build >= 26100.6584), and KB5070312 (23H2, build >= 22631.6276). Knowledge source: docs/agent/autopilot-ztd-diagnostics.md (error-code map).", + "description": "A Microsoft Entra hybrid join Autopilot deployment hit error 0x80004005 — a documented build-dependent known issue, resolved by KB5065789 (25H2, build >= 26200.6725), KB5065426 (24H2, build >= 26100.6584), and KB5070312 (23H2, build >= 22631.6276).", "severity": "high", "category": "enrollment", "version": "1.1.0", diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/SystemSignals/ModernDeploymentTrackerErrorBackfillTests.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/SystemSignals/ModernDeploymentTrackerErrorBackfillTests.cs index e04180cd..58eaff29 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/SystemSignals/ModernDeploymentTrackerErrorBackfillTests.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/SystemSignals/ModernDeploymentTrackerErrorBackfillTests.cs @@ -13,7 +13,7 @@ using Xunit; namespace AutopilotMonitor.Agent.V2.Core.Tests.Monitoring.SystemSignals { /// - /// Autopilot-channel error backfill (docs/agent/autopilot-ztd-diagnostics.md, + /// Autopilot-channel error backfill (internal/docs/agent/autopilot-ztd-diagnostics.md, /// Observability section): TPM/ZTD errors precede the agent's IME install, so a /// retry-then-success attempt leaves them in the event log with nobody watching. /// The backfill replays them as backfilled=true modern_deployment_error events; the diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Telemetry/DeviceInfo/ZtdEvidenceVerdictTests.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Telemetry/DeviceInfo/ZtdEvidenceVerdictTests.cs index 3dc47aad..47954947 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Telemetry/DeviceInfo/ZtdEvidenceVerdictTests.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Telemetry/DeviceInfo/ZtdEvidenceVerdictTests.cs @@ -7,7 +7,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.Telemetry.DeviceInfo; /// /// Pins the ZTD verdict mapping (autopilot_profile_missing evidence). The event-ID semantics /// come from the Microsoft Autopilot troubleshooting FAQ (see -/// docs/agent/autopilot-ztd-diagnostics.md): error IDs are authoritative and must win over +/// internal/docs/agent/autopilot-ztd-diagnostics.md): error IDs are authoritative and must win over /// the Info-flow reconstruction, and the priority order within the errors is /// registration (807) → identity mismatch (908) → deleted (809) → not assigned (815). /// diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Enrollment/SystemSignals/ModernDeploymentTracker.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Enrollment/SystemSignals/ModernDeploymentTracker.cs index 7246fd42..f6535fe9 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Enrollment/SystemSignals/ModernDeploymentTracker.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Enrollment/SystemSignals/ModernDeploymentTracker.cs @@ -22,7 +22,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.SystemSignals /// The Autopilot channel's documented event-ID semantics (100 waiting-for-profile, /// 153/160/161/163/164 profile-download flow, 171/172 TPM attestation, 807/809/815/908 /// ZTD registration/assignment errors) are catalogued with sources in - /// docs/agent/autopilot-ztd-diagnostics.md — re-check that doc's sources periodically. + /// internal/docs/agent/autopilot-ztd-diagnostics.md — re-check that doc's sources periodically. /// The continuous watcher here filters to Level ≤ 3; /// runs a targeted all-level one-shot query on the profile-missing path instead. /// @@ -50,7 +50,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Enrollment.SystemSignals /// registration/assignment errors (171/172, 807/809/815/908, all Level 1-2) happen /// BEFORE the agent is installed in the normal IME deployment model — a failed /// attempt that was resolved by a retry would stay invisible without replaying the - /// channel history at startup. See docs/agent/autopilot-ztd-diagnostics.md + /// channel history at startup. See internal/docs/agent/autopilot-ztd-diagnostics.md /// (Observability section). Fixed 4h lookback: OOBE start → agent install is /// normally well under that, and the RecordId watermark below prevents replays /// from re-emitting on every agent restart. diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/DeviceInfoCollector.NetworkAndSecurity.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/DeviceInfoCollector.NetworkAndSecurity.cs index a618b607..d684c101 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/DeviceInfoCollector.NetworkAndSecurity.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/DeviceInfoCollector.NetworkAndSecurity.cs @@ -292,7 +292,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Telemetry.DeviceInfo { // Second diagnostic surface (independent of AutopilotPolicyCache): Microsoft's // documented Diagnostics\Autopilot key (IsAutopilotDisabled, TenantMatched, - // CloudAssignedTenantDomain/Id, ...). See docs/agent/autopilot-ztd-diagnostics.md. + // CloudAssignedTenantDomain/Id, ...). See internal/docs/agent/autopilot-ztd-diagnostics.md. diagnosticsRegistry = ZtdEvidence.ReadDiagnosticsRegistry(_logger); if (diagnosticsRegistry != null) data["diagnosticsRegistry"] = diagnosticsRegistry; @@ -312,7 +312,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Telemetry.DeviceInfo // runs as a standard Entra join and would otherwise look like a regular // Autopilot session — surface the edge case explicitly, with a ZTD verdict // backed by the ModernDeployment Autopilot event log plus an endpoint probe - // (see docs/agent/autopilot-ztd-diagnostics.md for the evidence model). + // (see internal/docs/agent/autopilot-ztd-diagnostics.md for the evidence model). if (!isDevicePreparation && IsAutopilotProfileMissing(data)) { // On Windows 365 Cloud PCs a missing profile is the expected state — Cloud PCs diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/ZtdEvidence.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/ZtdEvidence.cs index d585e31f..fb01696c 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/ZtdEvidence.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/DeviceInfo/ZtdEvidence.cs @@ -26,7 +26,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Telemetry.DeviceInfo /// authoritative witness for reachability at check time. /// /// Event-ID meanings, registry values, and endpoint list are documented (with sources and - /// a re-check RSS feed) in docs/agent/autopilot-ztd-diagnostics.md — keep both in sync. + /// a re-check RSS feed) in internal/docs/agent/autopilot-ztd-diagnostics.md — keep both in sync. /// internal static class ZtdEvidence { diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/MsiProductVersionReaderTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/MsiProductVersionReaderTests.cs index 6e74397c..ca7b266b 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/MsiProductVersionReaderTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/MsiProductVersionReaderTests.cs @@ -154,7 +154,7 @@ public class MsiProductVersionReaderTests /// /// Sweeps every ime-files/<version>/IntuneWindowsAgent.msi in the repo checkout - /// (gitignored decompile scratch, populated by /ime-decompile) and asserts the reader + /// (gitignored local scratch, populated by an operator tool) and asserts the reader /// returns exactly the folder's version. Silently passes when the folder is absent (CI) /// — the synthetic tests above carry the contract there; this one pins the string-pool /// id convention against Microsoft's real packages. diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/RuleEngineEvaluateOnTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/RuleEngineEvaluateOnTests.cs index 4bc2af34..f884f12d 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/RuleEngineEvaluateOnTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/RuleEngineEvaluateOnTests.cs @@ -7,7 +7,7 @@ using Moq; namespace AutopilotMonitor.Functions.Tests; /// -/// evaluateOn interim-trigger semantics (docs/rules/analyze-rule-triggers.md): +/// evaluateOn interim-trigger semantics (internal/docs/rules/analyze-rule-triggers.md): /// trigger grammar + matching helpers, the engine's interim rule filter, the /// RuleResult update/finalize/resolve lifecycle replacing the permanent dedupe /// freeze, KO suppression on interim runs, and the ingest-side trigger registry. diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationRadarTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationRadarTests.cs index eea2e5dc..263c1690 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationRadarTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationRadarTests.cs @@ -9,7 +9,7 @@ using AutopilotMonitor.Shared.Models; namespace AutopilotMonitor.Functions.Tests; /// -/// Verdict-calibration drift radar (docs/backend/verdict-calibration.md): the three finding +/// Verdict-calibration drift radar (internal/docs/backend/verdict-calibration.md): the three finding /// kinds, the small-n / lift / Wilson gates, re-arm, and the tracker round-trip. /// public class VerdictCalibrationRadarTests diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationTests.cs index 0c2651bb..d1810856 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/VerdictCalibrationTests.cs @@ -9,7 +9,7 @@ using AutopilotMonitor.Shared.Models; namespace AutopilotMonitor.Functions.Tests; /// -/// Verdict calibration aggregate (docs/backend/verdict-calibration.md): the pure bucketing core, +/// Verdict calibration aggregate (internal/docs/backend/verdict-calibration.md): the pure bucketing core, /// the persistence round-trip and the matrix arithmetic of the read endpoint. /// public class VerdictCalibrationTests diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/VerdictPathTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/VerdictPathTests.cs index 08144eb5..bd9ae01a 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/VerdictPathTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/VerdictPathTests.cs @@ -7,7 +7,7 @@ using AutopilotMonitor.Shared.Models; namespace AutopilotMonitor.Functions.Tests; /// -/// Verdict calibration instrumentation (docs/backend/verdict-calibration.md): every status write +/// Verdict calibration instrumentation (internal/docs/backend/verdict-calibration.md): every status write /// declares its origin, overriding a prior verdict preserves it, the classifier names the rule /// behind each verdict, and pre-instrumentation rows derive an honest path from their literals. /// diff --git a/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableHardwareRejectionNotificationTracker.cs b/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableHardwareRejectionNotificationTracker.cs index 145a44bb..1b7c5592 100644 --- a/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableHardwareRejectionNotificationTracker.cs +++ b/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableHardwareRejectionNotificationTracker.cs @@ -422,7 +422,7 @@ namespace AutopilotMonitor.Functions.DataAccess.TableStorage }; } - // ===== VERDICT CALIBRATION DRIFT (docs/backend/verdict-calibration.md) ===== + // ===== VERDICT CALIBRATION DRIFT (internal/docs/backend/verdict-calibration.md) ===== internal const string VerdictCalibrationRowKeyPrefix = "verdictcalibration|"; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetVerdictCalibrationFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetVerdictCalibrationFunction.cs index 7debc494..9e845417 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetVerdictCalibrationFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetVerdictCalibrationFunction.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Metrics { /// - /// Operator-only verdict calibration matrix (docs/backend/verdict-calibration.md): per verdict + /// Operator-only verdict calibration matrix (internal/docs/backend/verdict-calibration.md): per verdict /// path, how many sessions it produced in the window, its share, how often it was overridden /// (admin / late completion / other), the 7-day re-enrollment proxy, and a 7d-vs-28d trend. /// Platform scope ("global" partition) or one tenant via ?tenantId=. Serves the admin diff --git a/src/Backend/AutopilotMonitor.Functions/Helpers/VerdictCalibrationRadar.cs b/src/Backend/AutopilotMonitor.Functions/Helpers/VerdictCalibrationRadar.cs index f7258082..9ebf47fa 100644 --- a/src/Backend/AutopilotMonitor.Functions/Helpers/VerdictCalibrationRadar.cs +++ b/src/Backend/AutopilotMonitor.Functions/Helpers/VerdictCalibrationRadar.cs @@ -27,7 +27,7 @@ public class VerdictCalibrationFinding /// /// Pure drift detection over one tenant's verdict-calibration daily rows -/// (docs/backend/verdict-calibration.md) — the same statistics as the rule-regression radar +/// (internal/docs/backend/verdict-calibration.md) — the same statistics as the rule-regression radar /// (7-day window vs the prior 28 days, lift ≥2×, Wilson-separated via /// , small-n gates) applied to three questions: /// diff --git a/src/Backend/AutopilotMonitor.Functions/Program.cs b/src/Backend/AutopilotMonitor.Functions/Program.cs index fff4f940..bcb937c4 100644 --- a/src/Backend/AutopilotMonitor.Functions/Program.cs +++ b/src/Backend/AutopilotMonitor.Functions/Program.cs @@ -71,7 +71,7 @@ builder.Services // 2026-08-23: solved differently — RequestTelemetryMiddleware sets SamplingPercentage=100 on its // own item (per-item sampling bypass), and the host duplicate is removed by a workspace DCR // transformation on AppRequests (keeps rows with Properties.Source=='WorkerMiddleware' plus -// non-HTTP host rows with empty Url, i.e. timer/queue invocations). See docs/backend/telemetry-ingest-shaping.md. +// non-HTTP host rows with empty Url, i.e. timer/queue invocations). See internal/docs/backend/telemetry-ingest-shaping.md. // Drop successful Azure Storage dependencies (Table/Queue/Blob) from the worker telemetry // pipeline to curb AppDependencies ingestion cost — this backend is storage-I/O heavy and those @@ -267,7 +267,7 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); // Cached per-tenant evaluateOn trigger sets for the ingest-side interim analyze enqueue -// (docs/rules/analyze-rule-triggers.md). Singleton so the 5-min TTL cache is shared. +// (internal/docs/rules/analyze-rule-triggers.md). Singleton so the 5-min TTL cache is shared. builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddHttpClient() diff --git a/src/Backend/AutopilotMonitor.Functions/Services/Analyze/AnalyzeOnEnrollmentEndHandler.cs b/src/Backend/AutopilotMonitor.Functions/Services/Analyze/AnalyzeOnEnrollmentEndHandler.cs index 31d385a9..9c778409 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/Analyze/AnalyzeOnEnrollmentEndHandler.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/Analyze/AnalyzeOnEnrollmentEndHandler.cs @@ -25,7 +25,7 @@ namespace AutopilotMonitor.Functions.Services.Analyze /// to match the legacy ReanalyzeAfterVulnerabilityEmitAsync behavior (avoids /// double-counting eval rows on already-stat'd rules). /// whiteglove_sealed / interim_trigger — evaluateOn-filtered interim - /// runs before the session is terminal (docs/rules/analyze-rule-triggers.md): persist + /// runs before the session is terminal (internal/docs/rules/analyze-rule-triggers.md): persist /// results + resolved rows, SignalR + channel notifications (NotifiedAt-deduped), skip /// platform-stat and rule-fire stats; the engine suppresses the KO escalation. /// diff --git a/src/Backend/AutopilotMonitor.Functions/Services/Analyze/InterimTriggerRegistry.cs b/src/Backend/AutopilotMonitor.Functions/Services/Analyze/InterimTriggerRegistry.cs index 5a2d0c79..8db73a68 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/Analyze/InterimTriggerRegistry.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/Analyze/InterimTriggerRegistry.cs @@ -17,7 +17,7 @@ namespace AutopilotMonitor.Functions.Services.Analyze /// (no interim enqueue — behavior degrades to the terminal-only baseline, never throws /// into the ingest path). The engine re-checks rule scope anyway, so registry staleness /// can only cost a wasted (cheap, rule-less) queue round-trip, never a wrong evaluation. - /// See docs/rules/analyze-rule-triggers.md. + /// See internal/docs/rules/analyze-rule-triggers.md. /// public class InterimTriggerRegistry { diff --git a/src/Backend/AutopilotMonitor.Functions/Services/CmTraceSkewTripwire.cs b/src/Backend/AutopilotMonitor.Functions/Services/CmTraceSkewTripwire.cs index 92c260a1..0e697862 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/CmTraceSkewTripwire.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/CmTraceSkewTripwire.cs @@ -7,7 +7,7 @@ namespace AutopilotMonitor.Functions.Services { /// /// Regression tripwire for the agent's CMTrace time resolution (per-line self-anchoring, - /// docs/agent/cmtrace-time-resolution.md). Runs once per session on the terminal ingest + /// internal/docs/agent/cmtrace-time-resolution.md). Runs once per session on the terminal ingest /// batch, over samples the counter reconcile collected in its existing partition scan. /// /// Detection: diff = median(Δ_IME) − median(Δ_other), where Δ = ReceivedAt − OccurredUtc. @@ -39,7 +39,7 @@ namespace AutopilotMonitor.Functions.Services internal static class CmTraceSkewTripwire { // Same grid the agent anchors on and the same residual tolerance as its own grid - // guard (docs/agent/cmtrace-time-resolution.md) — keep these in lockstep with the + // guard (internal/docs/agent/cmtrace-time-resolution.md) — keep these in lockstep with the // agent so a future anchoring change stays traceable to this detector. internal const int GridMinutes = 15; internal const double ResidualToleranceMinutes = 2.0; diff --git a/src/Backend/AutopilotMonitor.Functions/Services/EventIngestProcessor.cs b/src/Backend/AutopilotMonitor.Functions/Services/EventIngestProcessor.cs index 357234ce..80ce2be9 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/EventIngestProcessor.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/EventIngestProcessor.cs @@ -554,8 +554,8 @@ namespace AutopilotMonitor.Functions.Services /// /// /// Fire-and-forget enqueue of the installer-archive job for an IME version; the - /// producer is fail-soft (a lost message means "not auto-archived", the /ime-decompile - /// skill's blob backfill is the manual fallback). + /// producer is fail-soft (a lost message means "not auto-archived", the operator-side + /// blob backfill is the manual fallback). /// private Task EnqueueImeMsiArchiveAsync( string imeVersion, string? msiDownloadUrl, string? msiMatchedBy, IngestEventsRequest request) diff --git a/src/Backend/AutopilotMonitor.Functions/Services/Ime/AzureQueueImeMsiArchiveProducer.cs b/src/Backend/AutopilotMonitor.Functions/Services/Ime/AzureQueueImeMsiArchiveProducer.cs index 8ada8ef8..35cf61be 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/Ime/AzureQueueImeMsiArchiveProducer.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/Ime/AzureQueueImeMsiArchiveProducer.cs @@ -17,7 +17,7 @@ namespace AutopilotMonitor.Functions.Services.Ime /// /// Fault tolerance: queue-side exceptions are logged but never rethrown — the /// caller is the ingest path's fire-and-forget continuation. A missed enqueue means the - /// version's installer is not auto-archived; the /ime-decompile skill's blob backfill + /// version's installer is not auto-archived; the operator-side blob backfill /// is the manual fallback. /// /// @@ -72,7 +72,7 @@ namespace AutopilotMonitor.Functions.Services.Ime { // Fail-soft — ingest continuation. Skill-side blob backfill is the fallback. _logger.LogWarning(ex, - "ImeMsiArchive enqueue failed (version={Version}) — /ime-decompile blob backfill is the fallback", + "ImeMsiArchive enqueue failed (version={Version}) — operator-side blob backfill is the fallback", envelope.Version); } } diff --git a/src/Backend/AutopilotMonitor.Functions/Services/Ime/ImeMsiArchiver.cs b/src/Backend/AutopilotMonitor.Functions/Services/Ime/ImeMsiArchiver.cs index 1cd827a6..62afff5e 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/Ime/ImeMsiArchiver.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/Ime/ImeMsiArchiver.cs @@ -201,7 +201,7 @@ namespace AutopilotMonitor.Functions.Services.Ime /// (msiMatchedBy=productVersion, allowlisted), the version is not archived (and /// not permanently rejected as a bad version string), and the last archive activity is /// older than — or there never was any (versions sighted - /// before the archiver existed, or archived by hand via the /ime-decompile skill; the + /// before the archiver existed, or archived by hand by an operator; the /// 409 path then heals the row to Archived). /// public static bool ShouldRequeueOnSighting( diff --git a/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibration.cs b/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibration.cs index 82c8f1bf..9cd0b233 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibration.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibration.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Services { /// - /// Partial: verdict-calibration daily aggregates (docs/backend/verdict-calibration.md) — the + /// Partial: verdict-calibration daily aggregates (internal/docs/backend/verdict-calibration.md) — the /// operator thermometer for the rule classifier: which verdict path produced how many /// sessions per day, how many of those were later overridden (admin / late completion / /// other), and how many devices re-enrolled within 7 days. diff --git a/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibrationRadar.cs b/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibrationRadar.cs index e3b48963..76c63ef1 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibrationRadar.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.VerdictCalibrationRadar.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Services { /// - /// Partial: verdict-calibration drift radar (docs/backend/verdict-calibration.md). Same + /// Partial: verdict-calibration drift radar (internal/docs/backend/verdict-calibration.md). Same /// episode/tracker pattern as the rule-regression radar, over the verdict-calibration daily /// rows (). Operator-only: fires a VerdictCalibrationDrift /// ops event once per episode and surfaces the episode in the calibration endpoint's diff --git a/src/Backend/AutopilotMonitor.Functions/Services/OpsEventService.cs b/src/Backend/AutopilotMonitor.Functions/Services/OpsEventService.cs index b659e3f9..cd786ead 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/OpsEventService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/OpsEventService.cs @@ -737,7 +737,7 @@ namespace AutopilotMonitor.Functions.Services }); /// - /// Verdict-calibration drift radar (docs/backend/verdict-calibration.md): a verdict + /// Verdict-calibration drift radar (internal/docs/backend/verdict-calibration.md): a verdict /// path's share of sessions doubled over its 28d baseline, the silence share /// (sweep+maxlife — agent went quiet, backend had to decide) doubled, or the pure /// fallthrough rule r6 decides ≥20 % of classifier verdicts. Operator-only diagnostic — @@ -867,7 +867,7 @@ namespace AutopilotMonitor.Functions.Services /// The CMTrace time-skew tripwire fired: a terminal session's IME-derived event /// timestamps diverge from its other events by a clean 15-minute-grid multiple — /// the signature of a timezone mis-conversion the per-line self-anchoring - /// (docs/agent/cmtrace-time-resolution.md) failed to catch. Goal state: this event + /// (internal/docs/agent/cmtrace-time-resolution.md) failed to catch. Goal state: this event /// NEVER fires; any occurrence is a real anchoring regression or a detector bug, /// both actionable. Emitted by once per session /// (gated on the terminal status transition). The message carries the full numbers diff --git a/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs b/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs index 59462ce4..c51b211a 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs @@ -38,7 +38,7 @@ namespace AutopilotMonitor.Functions.Services /// /// Evaluates analyze rules against the full session event stream under an explicit run - /// context (see and docs/rules/analyze-rule-triggers.md). + /// context (see and internal/docs/rules/analyze-rule-triggers.md). /// /// Rule scope: Terminal/Reanalyze runs evaluate every active rule; Interim runs /// evaluate only rules whose evaluateOn matches the run's trigger. @@ -443,7 +443,7 @@ namespace AutopilotMonitor.Functions.Services /// /// Run context for . - /// Built from the queue envelope's Reason (see docs/rules/analyze-rule-triggers.md). + /// Built from the queue envelope's Reason (see internal/docs/rules/analyze-rule-triggers.md). /// public sealed class AnalyzeRunContext { diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs index b0cbd71c..fc25b1bb 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs @@ -210,7 +210,7 @@ namespace AutopilotMonitor.Functions.Services if (!string.IsNullOrEmpty(adminMarkedAction)) indexEntity["AdminMarkedAction"] = adminMarkedAction; - // Verdict calibration attribution (docs/backend/verdict-calibration.md): the aggregate + // Verdict calibration attribution (internal/docs/backend/verdict-calibration.md): the aggregate // sweep reads these off the session row, and the index mirror must not drop them on a // StartedAt-shift full upsert. foreach (var col in new[] { "VerdictPath", "PriorStatus", "PriorVerdictPath" }) diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.VerdictCalibration.cs b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.VerdictCalibration.cs index b8aaa992..be0b723d 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.VerdictCalibration.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.VerdictCalibration.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Services { /// - /// Partial: verdict-calibration daily aggregate persistence (docs/backend/verdict-calibration.md). + /// Partial: verdict-calibration daily aggregate persistence (internal/docs/backend/verdict-calibration.md). /// VerdictCalibrationAggregates: PK=TenantId ("global" for the cross-tenant row), /// RK="{yyyy-MM-dd}" — one row per (tenant, StartedAt date) holding the per-verdict-path /// buckets as a JSON column. Recomputed whole (Replace) by the maintenance sweep, 180d diff --git a/src/McpServer/autopilot-monitor-mcp/src/__tests__/lean-defaults.test.ts b/src/McpServer/autopilot-monitor-mcp/src/__tests__/lean-defaults.test.ts index 0ae79e63..512e5307 100644 --- a/src/McpServer/autopilot-monitor-mcp/src/__tests__/lean-defaults.test.ts +++ b/src/McpServer/autopilot-monitor-mcp/src/__tests__/lean-defaults.test.ts @@ -81,7 +81,7 @@ describe('first-page defaults', () => { it('a FILTERED get_session_events read stays complete: no projection, no omission marker', async () => { // Usage telemetry: filtered reads target specific events and want their payload about half the - // time (and the ime-decompile skill reads data.msiDownloadUrl after an eventType filter). + // time (and operator tooling reads data.msiDownloadUrl after an eventType filter). const handler = handlerFor('get_session_events'); const { urls } = stubFetchCapture(); diff --git a/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts b/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts index 110090ae..fe4f3b00 100644 --- a/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts +++ b/src/McpServer/autopilot-monitor-mcp/src/generated/wire-types.generated.ts @@ -226,7 +226,7 @@ export interface AnalyzeRule { provenance?: string; /** Rule trigger type: "single" (matches individual events) or "correlation" (combines multiple event types) Both types run at the same time during analysis - this field is organizational/descriptive */ trigger: string; - /** When this rule is evaluated. Null/empty = ["enrollment_end"] — the historical terminal-only behavior. Additional interim triggers let a rule fire before the session is terminal: "whiteglove_sealed" (first genuine whiteglove_complete seal) and "on_event:" (an ingest batch contained that event type). Interim runs suppress the KO path and record no stats — see AnalyzeRuleTriggers and docs/rules/analyze-rule-triggers.md. */ + /** When this rule is evaluated. Null/empty = ["enrollment_end"] — the historical terminal-only behavior. Additional interim triggers let a rule fire before the session is terminal: "whiteglove_sealed" (first genuine whiteglove_complete seal) and "on_event:" (an ingest batch contained that event type). Interim runs suppress the KO path and record no stats — see AnalyzeRuleTriggers and internal/docs/rules/analyze-rule-triggers.md. */ evaluateOn?: string[]; /** Optional device-fact gates evaluated BEFORE conditions. ALL preconditions must pass; if any fails the rule is silently skipped — no result, no UI card. Used to filter out hardware/OS profiles where a rule does not apply (e.g. "skip on virtual machines"). */ preconditions: RulePrecondition[]; diff --git a/src/McpServer/autopilot-monitor-mcp/src/rule-validation.ts b/src/McpServer/autopilot-monitor-mcp/src/rule-validation.ts index 49de5030..cee5ee08 100644 --- a/src/McpServer/autopilot-monitor-mcp/src/rule-validation.ts +++ b/src/McpServer/autopilot-monitor-mcp/src/rule-validation.ts @@ -403,7 +403,7 @@ function lintAnalyzeRule(rule: Record): ValidationFinding[] { }); } - // ── evaluateOn (interim evaluation) lints — docs/rules/analyze-rule-triggers.md ── + // ── evaluateOn (interim evaluation) lints — internal/docs/rules/analyze-rule-triggers.md ── const evaluateOn = (Array.isArray(rule.evaluateOn) ? rule.evaluateOn : []).filter( (t): t is string => typeof t === 'string', ); diff --git a/src/McpServer/autopilot-monitor-mcp/src/tools/admin.ts b/src/McpServer/autopilot-monitor-mcp/src/tools/admin.ts index 8d4dcaa2..c5b16454 100644 --- a/src/McpServer/autopilot-monitor-mcp/src/tools/admin.ts +++ b/src/McpServer/autopilot-monitor-mcp/src/tools/admin.ts @@ -982,7 +982,7 @@ export function registerAdminTools(server: McpServer, ga: boolean, strictGa: boo ); // Tool: get_verdict_calibration — platform scope (GA + Global Reader). Operator diagnostics for - // the session-verdict classifier (docs/backend/verdict-calibration.md) — never a customer surface. + // the session-verdict classifier (internal/docs/backend/verdict-calibration.md) — never a customer surface. if (ga) server.registerTool( 'get_verdict_calibration', { diff --git a/src/Shared/AutopilotMonitor.Shared/Constants.cs b/src/Shared/AutopilotMonitor.Shared/Constants.cs index 9feecdb4..058cf6b4 100644 --- a/src/Shared/AutopilotMonitor.Shared/Constants.cs +++ b/src/Shared/AutopilotMonitor.Shared/Constants.cs @@ -1063,7 +1063,7 @@ namespace AutopilotMonitor.Shared // VerdictCalibrationAggregates: PK=TenantId (or "global"), RK="{yyyy-MM-dd}" — daily // per-verdict-path buckets (count, derived, re-enrolled-within-7d, overridden-by-admin/ // late-completion) the operator calibration matrix + drift radar read - // (docs/backend/verdict-calibration.md). Additive across days; 180d retention; regenerable. + // (internal/docs/backend/verdict-calibration.md). Additive across days; 180d retention; regenerable. public const string VerdictCalibrationAggregates = "VerdictCalibrationAggregates"; // Configuration tables diff --git a/src/Shared/AutopilotMonitor.Shared/DataAccess/IMetricsRepository.cs b/src/Shared/AutopilotMonitor.Shared/DataAccess/IMetricsRepository.cs index 9bf6ae30..8ecadf7b 100644 --- a/src/Shared/AutopilotMonitor.Shared/DataAccess/IMetricsRepository.cs +++ b/src/Shared/AutopilotMonitor.Shared/DataAccess/IMetricsRepository.cs @@ -148,7 +148,7 @@ namespace AutopilotMonitor.Shared.DataAccess Task DeleteDeviceJourneyAggregateAsync(string tenantId, string dateKey); Task DeleteDeviceJourneyAggregatesOlderThanAsync(DateTime cutoffDate); - // --- Verdict calibration (docs/backend/verdict-calibration.md) --- + // --- Verdict calibration (internal/docs/backend/verdict-calibration.md) --- Task SaveVerdictCalibrationAggregateAsync(VerdictCalibrationDailyAggregate aggregate); /// Daily verdict-path rows of one tenant partition ("global" allowed), inclusive date range; counts are additive across days. Task> GetVerdictCalibrationAggregatesAsync(string tenantId, DateTime startDate, DateTime endDate); diff --git a/src/Shared/AutopilotMonitor.Shared/Models/AnalyzeOnEnrollmentEndEnvelope.cs b/src/Shared/AutopilotMonitor.Shared/Models/AnalyzeOnEnrollmentEndEnvelope.cs index c094fded..b0fe9b6a 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/AnalyzeOnEnrollmentEndEnvelope.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/AnalyzeOnEnrollmentEndEnvelope.cs @@ -13,7 +13,7 @@ namespace AutopilotMonitor.Shared.Models /// is the incremental rerun (no stats), and the interim reasons /// whiteglove_sealed / interim_trigger run the evaluateOn-filtered /// interim path (notify yes, KO + stats suppressed) — see - /// docs/rules/analyze-rule-triggers.md. + /// internal/docs/rules/analyze-rule-triggers.md. /// /// public sealed class AnalyzeOnEnrollmentEndEnvelope diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationAlert.cs b/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationAlert.cs index f47e71a6..eb46c993 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationAlert.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationAlert.cs @@ -2,7 +2,7 @@ using System; namespace AutopilotMonitor.Shared.Models { - /// Kinds of verdict-calibration drift the radar detects (docs/backend/verdict-calibration.md). + /// Kinds of verdict-calibration drift the radar detects (internal/docs/backend/verdict-calibration.md). public static class VerdictCalibrationAlertKinds { /// One verdict path's share of all sessions rose ≥2× over its 28-day baseline (Wilson-separated). diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationDailyAggregate.cs b/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationDailyAggregate.cs index 377fea5b..c7fe6d0a 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationDailyAggregate.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Metrics/VerdictCalibrationDailyAggregate.cs @@ -43,7 +43,7 @@ namespace AutopilotMonitor.Shared.Models /// /// Daily verdict-calibration rollup for one (tenant, date) — the operator's thermometer for the - /// rule classifier (docs/backend/verdict-calibration.md). A session buckets on its StartedAt + /// rule classifier (internal/docs/backend/verdict-calibration.md). A session buckets on its StartedAt /// date (same convention as every other daily aggregate; the rolling sweep re-buckets /// late-terminating sessions idempotently). Every status is counted — non-terminal rows are /// part of the picture (a growing Stalled share is a signal) — and diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRule.cs b/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRule.cs index 42cfaf25..48cfa5f2 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRule.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRule.cs @@ -81,7 +81,7 @@ namespace AutopilotMonitor.Shared.Models /// is terminal: "whiteglove_sealed" (first genuine whiteglove_complete seal) and /// "on_event:<eventType>" (an ingest batch contained that event type). /// Interim runs suppress the KO path and record no stats — see - /// and docs/rules/analyze-rule-triggers.md. + /// and internal/docs/rules/analyze-rule-triggers.md. /// public List? EvaluateOn { get; set; } diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRuleTriggers.cs b/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRuleTriggers.cs index c751a583..ce89599c 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRuleTriggers.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Rules/AnalyzeRuleTriggers.cs @@ -9,7 +9,7 @@ namespace AutopilotMonitor.Shared.Models /// consumer (engine rule filter, ingest trigger registry, CRUD validation) shares so /// the matching semantics cannot drift apart. An absent/empty EvaluateOn list means /// only — the historical terminal-only behavior, bit-for-bit. - /// See docs/rules/analyze-rule-triggers.md for the full design. + /// See internal/docs/rules/analyze-rule-triggers.md for the full design. /// public static class AnalyzeRuleTriggers { diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Rules/RuleResult.cs b/src/Shared/AutopilotMonitor.Shared/Models/Rules/RuleResult.cs index 3da03d2a..3b246996 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Rules/RuleResult.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Rules/RuleResult.cs @@ -77,7 +77,7 @@ namespace AutopilotMonitor.Shared.Models // ===== EVALUATION LIFECYCLE (evaluateOn interim triggers) ===== // All nullable: rows written before the feature read as final/terminal legacy results. - // See docs/rules/analyze-rule-triggers.md. + // See internal/docs/rules/analyze-rule-triggers.md. /// /// When this finding FIRST fired for the session (stable across interim refreshes and diff --git a/src/Shared/AutopilotMonitor.Shared/Models/VerdictPaths.cs b/src/Shared/AutopilotMonitor.Shared/Models/VerdictPaths.cs index 996007d2..2102d241 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/VerdictPaths.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/VerdictPaths.cs @@ -6,7 +6,7 @@ namespace AutopilotMonitor.Shared.Models /// Machine-readable vocabulary for — WHICH code path /// produced the session's current . Format is /// origin:detail, lower-case, stable: values are a persisted contract that the verdict - /// calibration aggregate (docs/backend/verdict-calibration.md) counts over days and tenants, so + /// calibration aggregate (internal/docs/backend/verdict-calibration.md) counts over days and tenants, so /// entries are append-only — never rename or reuse one. Unlike FailureSource (written /// only on Failed) the path is stamped for every status write, so a sweep "Incomplete", a late /// agent upgrade and an admin override are all countable. diff --git a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/verdictCalibrationLogic.ts b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/verdictCalibrationLogic.ts index 948d6b43..a9068622 100644 --- a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/verdictCalibrationLogic.ts +++ b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/verdictCalibrationLogic.ts @@ -1,5 +1,5 @@ /** - * Pure helpers for the Verdict Calibration matrix (docs/backend/verdict-calibration.md). + * Pure helpers for the Verdict Calibration matrix (internal/docs/backend/verdict-calibration.md). * Wire shape mirrors GetVerdictCalibrationFunction / VerdictCalibrationResponse (camelCase). */ diff --git a/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx b/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx index 99c19299..d3b52282 100644 --- a/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx +++ b/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx @@ -255,7 +255,7 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { // drains it all at once (p95 ~0.9s but a tail reaching 150s+), so the navigation the user // actually wants is stuck behind it and the portal freezes. Every route here is a client component behind // ProtectedRoute that fetches its own data after mount, so the prefetched RSC payload - // buys nothing. See docs/web/portal-navigation-prefetch.md. + // buys nothing. See internal/docs/web/portal-navigation-prefetch.md. // --- Render a global nav link --- const renderGlobalItem = (item: NavItem, isGlobal = false) => { const active = isNavActive(item.href); diff --git a/src/Web/autopilot-monitor-web/lib/timeProvenance.ts b/src/Web/autopilot-monitor-web/lib/timeProvenance.ts index 5fba8f41..24479db3 100644 --- a/src/Web/autopilot-monitor-web/lib/timeProvenance.ts +++ b/src/Web/autopilot-monitor-web/lib/timeProvenance.ts @@ -3,7 +3,7 @@ * CMTrace-derived events with how their UTC timestamp was produced — the raw local time * as written in the log, the applied UTC offset and its origin, the purely observational * per-file writer offset, and the clock-fallback markers. All values arrive as STRINGS - * inside the event data payload (see docs/agent/cmtrace-time-resolution.md). + * inside the event data payload (see internal/docs/agent/cmtrace-time-resolution.md). * * The timeline sorts by sequence — always, never by time (user guardrail). A displayed * time that steps BACKWARDS within that order is therefore information, not a rendering diff --git a/src/Web/autopilot-monitor-web/utils/shared-manifests.json b/src/Web/autopilot-monitor-web/utils/shared-manifests.json index 8be9297d..b5e2e93a 100644 --- a/src/Web/autopilot-monitor-web/utils/shared-manifests.json +++ b/src/Web/autopilot-monitor-web/utils/shared-manifests.json @@ -1484,7 +1484,7 @@ } }, "optional": true, - "doc": "When this rule is evaluated. Null/empty = [\"enrollment_end\"] — the historical terminal-only behavior. Additional interim triggers let a rule fire before the session is terminal: \"whiteglove_sealed\" (first genuine whiteglove_complete seal) and \"on_event:\" (an ingest batch contained that event type). Interim runs suppress the KO path and record no stats — see AnalyzeRuleTriggers and docs/rules/analyze-rule-triggers.md." + "doc": "When this rule is evaluated. Null/empty = [\"enrollment_end\"] — the historical terminal-only behavior. Additional interim triggers let a rule fire before the session is terminal: \"whiteglove_sealed\" (first genuine whiteglove_complete seal) and \"on_event:\" (an ingest batch contained that event type). Interim runs suppress the KO path and record no stats — see AnalyzeRuleTriggers and internal/docs/rules/analyze-rule-triggers.md." }, { "name": "preconditions", diff --git a/src/Web/autopilot-monitor-web/utils/wire-types.generated.ts b/src/Web/autopilot-monitor-web/utils/wire-types.generated.ts index 5f58e539..6c4c97b6 100644 --- a/src/Web/autopilot-monitor-web/utils/wire-types.generated.ts +++ b/src/Web/autopilot-monitor-web/utils/wire-types.generated.ts @@ -226,7 +226,7 @@ export interface AnalyzeRule { provenance?: string; /** Rule trigger type: "single" (matches individual events) or "correlation" (combines multiple event types) Both types run at the same time during analysis - this field is organizational/descriptive */ trigger: string; - /** When this rule is evaluated. Null/empty = ["enrollment_end"] — the historical terminal-only behavior. Additional interim triggers let a rule fire before the session is terminal: "whiteglove_sealed" (first genuine whiteglove_complete seal) and "on_event:" (an ingest batch contained that event type). Interim runs suppress the KO path and record no stats — see AnalyzeRuleTriggers and docs/rules/analyze-rule-triggers.md. */ + /** When this rule is evaluated. Null/empty = ["enrollment_end"] — the historical terminal-only behavior. Additional interim triggers let a rule fire before the session is terminal: "whiteglove_sealed" (first genuine whiteglove_complete seal) and "on_event:" (an ingest batch contained that event type). Interim runs suppress the KO path and record no stats — see AnalyzeRuleTriggers and internal/docs/rules/analyze-rule-triggers.md. */ evaluateOn?: string[]; /** Optional device-fact gates evaluated BEFORE conditions. ALL preconditions must pass; if any fails the rule is silently skipped — no result, no UI card. Used to filter out hardware/OS profiles where a rule does not apply (e.g. "skip on virtual machines"). */ preconditions: RulePrecondition[];