All three components now report <major>.<minor>.<build> plus a 7-char commit and a build timestamp. The backend had been pinned at a hand-written 1.0.0 since inception and starts at 1.5.1000; the MCP server's package.json version was bumped by hand and starts at 1.5.300, and it now reports its own commit on /health instead of only the documentation bundle's. The build number keeps coming from a counter blob reserved before the build with ETag-CAS, but there is now one implementation instead of two copies: .github/scripts/Request-BuildNumber.ps1, called by all three workflows and by the local build.ps1. It lives under .github/ because scripts/Deployment/ is gitignored (those scripts carry SAS tokens) and would therefore be absent from a CI checkout; scripts/Build/ and scripts/Release/ are shadowed by the [Bb]uild/ and [Rr]elease/ artifact ignores. The counter cannot be replaced by the published manifest, which is the obvious simplification to reach for: version.json is written only on stable publish, so two consecutive dev builds would derive the same number and the second would overwrite the first's artifact. git rev-list --count fails the same way, two builds of one commit collide. Both deploy workflows now poll their health endpoint until it reports exactly the version and commit just deployed, and publish versions/<component>.json only then. A green deploy step alone means the package was accepted, not that it is being served -- so a manifest that disagrees with the live endpoint now means the running instance drifted (rollback, stale revision) rather than a pipeline that stopped halfway. The agent manifest gains the same commit and buildUtc fields additively; the bootstrap reads it by field name, so older installers ignore them, and sha256/bootstrapVersion stay untouched. Requires the versions container plus AZURE_BLOB_VERSIONS_SAS_TOKEN and the two seeded counters (backend 999, mcp 299) before the first deploy run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
12 KiB
Log
2026-07-22
-
Creation: Added
versioning.md— agent, backend and MCP now share one version shape (<major>.<minor>.<build>+ 7-char commit + build timestamp) and one implementation of the build-number reservation (.github/scripts/Request-BuildNumber.ps1, previously copy-pasted betweenbuild-agent.ymlandbuild.ps1). The backend had been pinned at a hand-written1.0.0since inception and now starts at1.5.1000; the MCP server'spackage.jsonversion was bumped by hand and now starts at1.5.300, and it reports its own commit on/healthinstead of only the documentation bundle's. Both deploy workflows poll their health endpoint until it reports the build just deployed and publishversions/<component>.jsononly then, so a manifest that disagrees with the live endpoint means the instance drifted rather than the pipeline failing halfway.agent/build-counter-blob.mdkeeps the agent-specific parts and now points at the shared protocol; its counter URL was still the pre-cutover storage account. -
Creation: Added
rules/gather-rule-guardrails.md— the gather-rule allowlists are enforced only on the agent (the backend validates nocollectorType,target, orparameters), so a collector that forgets to call its guard is the vulnerability. Written because two had:LogParserCollectorread any path inrule.Target, bypassing even theC:\Usershard block that every other file collector honours, andEventLogCollectorread any channel includingSecurity— while the customer-facing documentation already promised both were allowlisted. Both now guard, withlogparserchecking the directory for wildcard targets (Path.GetFullPaththrows on*) and re-checking each resolved path. Added an event-log channel allowlist (eventLogChannels) plus hard-blocked channels held in C# rather than JSON, so a parse error cannot lift them. Also fixed the command timeout, which was inert:ReadToEnd()blocks until the pipe closes, soWaitForExit(30000)was only reached after the process had already exited and a hung command pinned its worker forever — now read asynchronously and killed at the timeout. -
Update: Added
.github/workflows/ci.yml— the full suite (backend, agent V2 Core, DecisionCore, SummaryDialog, web, MCP) now runs on every pull request and every push to main, plus a job that fails if the generated guardrail files drift fromrules/guardrails.json. Previously no workflow ran tests on a PR: the deploy workflows build without testing, andbuild-agent.ymltested onlyDecisionCore.Testson manual dispatch — whiletrust/security-faq.mdalready told customers that automated tests run in CI. Added CodeQL (C# and TypeScript) and Dependabot (nuget, npm ×2, actions). MarkedOfficeBinaryWatcherTests[Collection("SerialThreading")]: its bounded re-probe races the shared ThreadPool and failed once under full-suite load.
2026-07-21
-
Update:
search_docsandsearch_knowledgenow state in their tool descriptions that queries must be in English. Both corpora andall-MiniLM-L6-v2are English-only, and the failure is total rather than gradual — a German question returns zero results, not weak ones. The caller is a language model, so translating the question before the call and answering in the user's language costs nothing; a multilingual embedding model would be the alternative but is much larger and would have to be measured against the eval harness first, since it changes English retrieval too. -
Update: Added
scripts/eval-docs-search.ts, an offline retrieval evaluation harness (2465 queries in three classes: chunk headings as a regression detector, rare identifiers, and hand-written questions as the reality anchor), and used it to close a thirdsearch_docsgap found during the live test. The keyword fallback only fired when semantic search returned fewer thantopK; a pasted identifier likeWOW6432Nodeinstead returned three chunks at ~0.29 that did not contain the word while the one chunk that did was never considered. It now also fires on a weak semantic head (<0.35), letting exact matches take the front while keeping one semantic result. The threshold is measured, not guessed: 0.35 fixes 335 queries and breaks 0 (identifier recall 66.2% → 81.1%), while 0.40 fixes more but starts demoting hand-written questions. The measurement also resized the problem — identifier queries were only succeeding 66.2% of the time, so the reported case was one of roughly 750. -
Update: Closed the two measured recall gaps in
search_docs(mcp/docs-corpus.md). (1) Token windows — 87 of 324 chunks exceeded the model's 256-token context and 13% of all tokens never reached the ranking; a character budget cannot fix this (the corpus ranges 2.43–5.81 chars/token), so long text is now embedded as 250-token windows with 40 overlap and scored by its BEST window (embeddings: number[][], max not mean). Token coverage 87% → 100%; "proxy configuration blocking app downloads" went from absent to 0.559 at rank 1; the ten reference queries kept byte-identical scores. Costs +31% vectors, index 2.63 → 3.12 MB. The rules corpus gained the same treatment (128 rules → 172 vectors). (2) Keyword fallback — when the semantic pass returns fewer thantopK, results are topped up via literallexicalMatchon distinctive query terms, requiring two matching terms for corroboration (one incidental substring match returned a page about LLM providers for a sourdough query). Fuzzy matching was measured and rejected: at a threshold low enough to surface "RealmJoin" it invents 5 hits for "SCEPman", which the corpus never mentions. Also sharpened the tool description with the measured context argument for preferring it over fetching the docs site. -
Creation: Added
mcp/docs-corpus.md(newmcp/section) — the MCP server gainssearch_docs, a third semantic corpus built from the published customer documentation repository (autopilotmonitor-docs, checked out into the Docker build context by the deploy workflow). Documents the h2/h3 +<details>chunking with breadcrumb prefixes, the two deliberate size exceptions (tables never split, unbroken changelog lists split at line level), the CRLF precondition (.does not match\rin JS — headings silently stop matching, which produced 286 wrong-but-plausible chunks before it was found), the optionaldocssection insearch-index.jsonand its validation asymmetry, embedding rounding to 6 decimals, and the cross-repo coupling: a docs edit reaches clients only after an MCP redeploy, made checkable viaDOCS_COMMITon/health. Container resources raised to 0.5 vCPU / 1.0 GiB for the cold-start query-embedder load.
2026-07-20
-
Update:
rules/gather-rule-phase-scoping.md— the gather-rule form now shows the phase-scope and emit-mode controls only where they can change behavior (supportsPhaseScope/supportsEmitMode), nulls hidden-control state out of the payload, and rejects a scope mode selected but left unfilled. Offering all three "when" controls unconditionally allowed combinations that could only suppress a one-shot rule, plus a silent no-op state. -
Update: Extended
rules/gather-rule-phase-scoping.mdwith thephase_exittrigger — the closing bookend tophase_change, for one-shot collection when a phase is LEFT (e.g. "state at the end of Account Setup"). Documents the evaluation-before-phase-advance rule (triggerPhase match and scope gate see the phase being left), firing intoFailed, the disjointexit:dedup key space, and why no ConfigVersion bump is needed (no new field — old agents simply never fire the rule). -
Update: Reworked
agent/mdm-reboot-coalescing.mdafter the first real enrollment (session b2e890c1): 2800 records are now aggregated per burst into ONE neutral Info event (rebootUris[]/uriCount/firstRebootUri; watermark persisted at flush so a pre-emit reboot kill loses nothing); the raw event no longer claims a reboot — ANALYZE-ESP-005 is gated on an actually-observedsystem_reboot_detected. Removed the Shell-Coreesp_reboot_coalescingevent entirely: the "RebootCoalescing" token appears in the routineSubcategoryProcessing_Startedbootstrap marker on every enrollment (false positive by construction). Verified 2800 description shape recorded. -
Creation: Added
agent/mdm-reboot-coalescing.md— the agent now attributes the "unexpected mid-ESP reboot + second sign-in" pattern (PMPC research) to the device-assigned policy URIs that forced it: newMdmRebootPolicyTracker(DM-Enterprise EventID 2800, per-URImdm_policy_reboot_requiredevents, cross-restart RecordId watermark), aRebootCoalescingbranch inShellCoreTracker(esp_reboot_coalescing, backfill-emitting by design), and theANALYZE-ESP-005advisory (reassign device → user groups). ConfigVersion 35; event types deliberately distinct fromsystem_reboot_detectedso RebootCount stays uninflated. -
Creation: Added
backend/business-timestamps.md(newbackend/section) — the 2026-07-18 migration reset every row's system Timestamp, exposing that AuditLogs/OpsEvents/Events had (unknowingly) displayed and filtered on it all along; documents theOccurredUtccolumn, the RowKey decoders and RowKey-range date/retention clauses inBusinessTimestamp, the GUID-guard trap, the audit/ops backfill endpoint, and the "system Timestamp is never authoritative" migration rule. -
Creation: Added
rules/gather-rule-phase-scoping.md(newrules/section) — gather rules gainactivePhases(run only during listed phases),activeFromPhase(sticky latch from a phase onwards, never via Failed) andemitMode: "on_change"(canonical-hash result dedup withsuppressedPollsobservability), ConfigVersion 34. Includes the prerequisite backend fix: the custom-rule toggle PUT no longer wipes the stored rule definition (partial-merge inGatherRuleService.UpdateRuleAsync).
2026-07-18
- Creation: Added
agent/endpoint-migration.md— config-channel agent re-home (MigrateToApiBaseUrlonGET agent/config, ConfigVersion 33): backend or per-tenant API-URL moves without DNS indirection (impossible due to mTLS/Flex-TLS). Live-fetch-only with cache strip,AgentEndpointMigrationRulesallowlist validated on both sides, one hop, kill-switch wins. Built as the lesson from the 2026-07-18 WEU→GWC cutover, which hard-cut all in-flight agents.
2026-07-17
- Creation: Added
agent/build-counter-blob.md— agent build numbers now come from a shared public counter blob (buildcounter-v{N}.txt, reserve-before-build with ETag-CAS) so localbuild.ps1and CIbuild-agent.ymlbuilds can never mint the same number. Documents the CI parity fixes (SummaryDialog.exe.config in the ZIP, EXE-vs-manifest version check, hash-oracle update gated on stable cutover) and the Sigstore provenance attestation on CI-built ZIPs.
2026-07-16
- Creation: Added
agent/autopilot-ztd-diagnostics.md— reference for Windows' own ZTD diagnostic surfaces (ModernDeployment Autopilot event IDs incl. 807/809/815/908, theDiagnostics\Autopilotregistry key, deployment-service endpoints, known-issue error-code map with KB fixes). Backs the agent'sZtdEvidencecollector (ztdVerdictonautopilot_profile_missing) and the backend known-issue rules; sources carry a re-check RSS feed.
2026-07-13
-
Removal: Moved
customer-graph-add-on-permissions.mdout of this contributor bundle into the customer documentation repository (reference/optional-graph-permissions.md). It was customer-facing product content and did not belong in the tech-docs bundle; removed the entry fromindex.md. -
Creation: Added
agent/hello-wizard-unskip.md— session 772fe502 fix: theHelloWizardStarteddecision signal (prevention veto + un-skip cure for the policy-disabled Hello shortcut) and the HelloTracker confirmation second read against flip-flopping WHfB CSP values.
2026-07-11
-
Creation: Added the
agent/section — three concept documents on the V2 agent:agent/overview.md(runtime, collectors, telemetry pipeline),agent/decision-engine.md(DecisionCore reducer, signals, A/B/C completion arms, invariants),agent/logs-and-persistence.md(persisted artifacts, signal log vs spool, recovery/replay flow) plusagent/index.md. -
Creation: Converted
docs/into an OKF v0.1 knowledge bundle — added YAML frontmatter toarchitecture.md,mcp-oauth-flow.md, andcustomer-graph-add-on-permissions.md; createdindex.mdand this log.