Skip to content

What's New

Stay up to date with framework changes, new controls, and playbook additions. The full changelog is mirrored below from the repo root CHANGELOG.md.

Get Notified

Star the repository and use Watch > Releases to receive update notifications.


[Unreleased]

Added

  • Automation honesty guard (scripts/check_automation_honesty.py). New required step in the manifest / index / nav drift job asserting that each control's manifest automation claim is backed by wired evaluators: full requires every check to resolve to a registered EVALUATORS entry in assessment/engine/score.py, partial requires at least one. Understating automation never fails, because an understated claim is the fail-closed direction — the reviewer is asked for evidence the engine could in principle have collected. Pre-existing drift (43 controls) is recorded in assessment/manifest/automation-honesty-baseline.json, which is a one-way ratchet: --write refuses to add control IDs that are not already listed, so a newly introduced overclaim cannot be regenerated away. The same job now also runs assessment/manifest/generate_manifest.py --check, so controls.json must stay derivable from its generator. Covered by scripts/test_check_automation_honesty.py (32 tests).
  • Playwright container pin-drift guard (scripts/check_playwright_pin_drift.py). New required check (folded into the manifest / index / nav drift job) asserting every workflow container.image: mcr.microsoft.com/playwright:<tag> pin (e2e.yml, update-snapshots.yml) matches the @playwright/test version in package.json, ignoring the distro suffix and the unrelated @axe-core/playwright package. Runtime-install workflows (e2e-smoke.yml, prod-smoke*.yml) are out of scope by design. Closes the #583 class of failure where a Dependabot minor bump silently skews a pinned image against the client. Covered by scripts/test_check_playwright_pin_drift.py (9 tests).
  • Dependabot auto-merge (.github/workflows/dependabot-automerge.yml, repo var DEPENDABOT_AUTOMERGE). Kill-switch-gated pull_request_target workflow (never checks out PR code) that enables gh pr merge --auto --squash for minor/patch + security Dependabot updates; majors are labelled needs-review. The merge is still gated on every required check (including the pin-drift guard), so the semver level is not the safety boundary — the required checks are. Off by default; activated via DEPENDABOT_AUTOMERGE=true.
  • Regulatory Monitor state-only auto-merge (.github/workflows/regulatory-monitoring.yml, repo var REGULATORY_STATE_AUTOMERGE). Mirrors the Learn Monitor pattern — concurrency group, add-paths restricted to data/monitor-state.json(.backup) + reports/monitoring/*.md, consolidation of superseded monitoring/regulatory-<run> PRs, and a fail-closed file allowlist — with a stricter gate: it auto-merges a state-only baseline PR only when 0 CRITICAL and 0 HIGH items, computed from a fail-closed automerge_eligible signal (an empty/unparseable count is never read as "0", so a report-format drift can never slip an unreviewed item through). CRITICAL/HIGH PRs keep needs-review for a human, and consolidation never closes a needs-review PR. Off by default; activated via REGULATORY_STATE_AUTOMERGE=true.
  • e2e-full main-breakage alert (.github/workflows/e2e.yml, notify-e2e-failure job). e2e-full is label-gated off PRs and intentionally not a required check (making it required would deadlock unlabelled PRs), so a failure on main could otherwise go unseen. On a failed main push or the daily schedule run, the job now opens — or comments on — a single deduped e2e-full-broken issue (creating the label if missing), with issues: write scoped to that job only. Idempotent: never spams duplicates.
  • Runbook: Stage 2 redirect auto-merge activation (.github/AUTODOC-RUNBOOK.md). Maintainer-only documentation of how to activate the (already-merged, gated-OFF) redirect auto-merge: the AUTOMERGE_ENABLED master switch and AUTOMERGE_MIN_SAMPLES/MIN_WEEKS/MIN_AGREEMENT/WINDOW_DAYS thresholds, the activation steps (make autodoc-redirect-verify a required check, then flip AUTOMERGE_ENABLED after weeks of merged-as-is agreement), the kill-switch, and a note that the automated auto-revert workflow is deferred by design (revert detection is already in place).
  • Redirect auto-merge unlock gate + agreement ledger (Stage 2 s2-1, part 1 — scripts/autodoc_automerge.py). Second half of Stage 2, built gated OFF. A fail-closed multi-condition gate decides whether the runner may enable GitHub auto-merge on a deterministic redirect PR: it requires the master switch AUTOMERGE_ENABLED=true and at least AUTOMERGE_MIN_SAMPLES terminal samples spanning AUTOMERGE_MIN_WEEKS weeks and a merged-exactly-as-is rate ≥ AUTOMERGE_MIN_AGREEMENT and zero post-merge reverts in the window (all thresholds env-tunable, conservative defaults — decide-late). The agreement ledger (data/autodoc-automerge-ledger.json) records each auto-drafted redirect PR and its human outcome; "merged exactly as-is" is classified by re-running the same independent verifier the CI gate uses (autodoc_redirect_ci_verify) on the merged diff and confirming it is a clean swap of the same old→new URLs (a human edit counts as merged_edited, not agreement). The runner now records each redirect PR, reconciles past sample outcomes each run, and enables GitHub auto-merge only when the gate unlocks — so even when unlocked, auto-merge still fires only after the required autodoc-redirect-verify check is green (never bypassing CI). Off by default and inert until AUTOMERGE_ENABLED=true plus accumulated agreement. Covered by scripts/test_autodoc_automerge.py (16 tests, incl. future-dated/unreconciled-ledger poisoning guards) + auto-merge integration tests in scripts/test_autodoc_runner.py.
  • Independent CI re-verification for redirect PRs (Stage 2 backstop — scripts/autodoc_redirect_ci_verify.py, .github/workflows/autodoc-redirect-verify.yml). First half of Stage 2 (per-category redirect auto-merge), built ready but inert. A new pull_request_target workflow runs on every PR and self-shims: for any PR that is not a runner redirect PR (head not autodoc/* or missing the autodoc label) it reports success immediately, so it is safe to enable as a required status check without deadlocking normal PRs. For a runner redirect PR it re-derives the clean-swap verdict from the actual PR diff (read via API, verifier run from the base checkout — never PR code) and fails closed unless the diff is exactly one removed + one added table row in docs/reference/microsoft-learn-urls.md differing only in one well-formed-URL cell. This is the independent gate that Stage 2 auto-merge will be conditioned on (re-checking the diff on GitHub's side rather than trusting the runner's own pre-PR verification). It does not become a required check or change human-merge behavior until auto-merge is wired and enabled. Covered by scripts/test_autodoc_redirect_ci_verify.py (16 tests: clean swap, hunk-aware parsing (hidden ---/++ lines, second-file-after-hunk), wrong/multiple files, two-line, extra-cell, non-table, non-URL cell, trailing-junk URL, identical URLs, cell-count mismatch, CLI exit codes).
  • Autodoc scheduler + activation runbook (Phase 3 — pipeline complete). scripts/Register-AutodocTask.ps1 registers the daily Windows Scheduled Task that runs the unattended runner (pruning stale worktrees first; PSScriptAnalyzer-clean). The maintainer runbook .github/AUTODOC-RUNBOOK.md is finalized: full component table, the two AUTODOC_ENABLED switches (the local env var that gates the runner vs the repo variable that gates the CI verify gate / F5), end-to-end provisioning (Copilot CLI EMU login, judeper git creds, register task, set both switches), operations (disable/inspect/dry-run, stale-worktree cleanup, escalation), and a portability section for onboarding FSI-CopilotGov / FSI-CopilotGov-Solutions (via per-repo autodoc_route allowlists and the AUTODOC_REPO env var). The published description (docs/reference/learn-monitor-ai-enhancement.md) is flipped to implemented. With this, the local-CLI pivot is complete; the pipeline remains off by default.
  • Unattended autodoc runner (scripts/autodoc_runner.py). Phase 2 of the local-CLI pivot — the orchestration engine. On a schedule it reads the latest Learn Monitor report, routes each change (autodoc_route), and for every autodraft change: drafts a minimal doc edit with the GitHub Copilot CLI (headless), gates it through the deterministic verifier (autodoc_verify_gate) and the independent cross-model review (autodoc_cli_review, a different Copilot model family), and — only when both pass — opens a pull request for a human to merge. Failures retry a bounded number of times (autodoc_retry.decide, default 2) then escalate to a human; human-routed changes are never drafted (escalation issue only); per-change failures are fault-isolated; idempotent via the data/autodoc-ledger.json fingerprint ledger. Off by default — run() is a no-op unless AUTODOC_ENABLED=true. All side effects (draft/verify/review/git/PR/escalate) are isolated module functions so the orchestration is unit-tested by monkeypatching; covered by scripts/test_autodoc_runner.py (25 tests: combine-conclusion matrix, contract extraction, both-pass→PR, draft-needs-human/empty-diff→escalate, deterministic-needs-human→escalate, retry-then-succeed, exceed-fix-cycles→escalate, review-fail→escalate, base-branch restoration, disabled no-op, human-route escalation, fault isolation).
  • Independent cross-model autodoc reviewer (scripts/autodoc_cli_review.py). Phase 2 of the local-CLI pivot: the faithfulness check that replaces the retired third-party LLM verifier. It re-reviews a drafted doc edit with a different GitHub Copilot model family (passed via --model) so the author never grades its own work, treating the Learn change report as source-of-truth and the diff's added lines as the claims to verify. The single Copilot CLI call is isolated behind a mockable runner; everything fails closed — an exec failure yields needs_human, any malformed/non-conforming model output yields fail (never a silent pass). The reviewer runs with write/shell tools denied so it cannot mutate the repo. Covered by scripts/test_autodoc_cli_review.py (17 tests: prompt assembly, tolerant JSON extraction, fail-closed coercion, runner mocking, exit codes).
  • Autonomous Learn Monitor documentation pipeline — workflow layer (Stage 1, opt-in). Wires the merged scaffolding into a runnable, fail-closed, human-merge-gated pipeline, off by default (AUTODOC_ENABLED repo variable): scripts/autodoc_route.py (classify the latest Learn report → an authoring contract per change, fingerprint-idempotent via data/autodoc-ledger.json); autodoc-verify.yml + scripts/autodoc_verify_gate.py (shim-aware required check running the deterministic verifier, hardened pull_request_target, fails closed); bounded retry/escalation decision logic in scripts/autodoc_retry.py. Maintainer operations + provisioning in .github/AUTODOC-RUNBOOK.md; published description updated in docs/reference/learn-monitor-ai-enhancement.md. The F5 baseline-deferral ledger (advance the monitor baseline only when the downstream doc task is terminal) is implemented and gated off (scripts/autodoc_defer.py, scripts/autodoc_advance.py, .github/workflows/learn-monitor-advance.yml) — a byte-identical no-op unless AUTODOC_ENABLED=true. Each piece independently reviewed (cross-family owl-mode) before merge.
  • .github/CODEOWNERS — human review gate for compliance-sensitive paths. Names @judeper as required reviewer for customer-facing compliance content (docs/controls/, docs/reference/, docs/framework/, docs/playbooks/, mkdocs.yml), the control manifest, and the autonomous-pipeline safety machinery (scripts/autodoc_*.py, workflows). Scaffolding for the autonomous Learn Monitor pipeline's human-merge gate (Stage 1). Note: this becomes an enforced gate only once branch protection on main is set to "Require review from Code Owners" (a tracked admin prerequisite — main currently requires 11 status checks but no code-owner review).
  • Deterministic, fail-closed autodoc routing classifier (scripts/autodoc_classifier.py). First component of the autonomous Learn Monitor documentation pipeline (Stage 1). Parses a Learn Monitor change report and decides, per change, whether it is mechanically safe for an agent to draft a doc edit (route="autodraft", human still merges) or must be analyzed by a human (route="human"), plus a much stricter automerge_eligible flag for a future Stage 2. The decision is deterministic (no LLM) and fail-closed: regulatory citations, dates/deadlines, retention durations, license SKUs, deprecations, policy language, overclaim words, and any edit to existing control prose always route to a human, regardless of the monitor's own (noisy) CRITICAL/HIGH/MEDIUM tier. Covered by 20 unit/integration tests (scripts/test_autodoc_classifier.py) including real report fixtures. Implements the June 2026 council review's top finding (the form-vs-meaning classifier gap).
  • Autodoc canary / poison-pill guard (scripts/autodoc_canary.py). A standing safety guard that feeds deliberately bad changes (hallucinated citation, fabricated retention duration, overclaim, deprecation, license-SKU change, control-prose edit, CRITICAL tier, future deadline) through the routing gate and fails loudly (exit 1) if any is mis-promoted for unattended handling — the deterministic half of the "who verifies the verifier" control. Extension point reserved for the future cross-vendor LLM verifier. Covered by scripts/test_autodoc_canary.py.
  • Control 2.27 — Consumption-Entitlement Governance (Pillar 2 — Management). New framework control governing who is entitled to consume metered and premium Microsoft Copilot capabilities — enforcing a switch-on-pathway entitlement contract per agent consumption pathway, applying per-agent spend caps, and running a pre-enforcement coverage-gap ("who would be blocked") analysis before any spend control is activated. Pairs with Control 3.5 (cost reporting) and is distinct from Control 2.26 (agent identity governance) and Control 1.18 (functional RBAC). Documents the companion copilot-billing-governance solution's entitlement contract. Catalog expands from 78 to 79 controls (Pillar 2 from 26 to 27). Added to assessment/manifest/controls.json, CONTROL-INDEX.md, mkdocs.yml, and the Pillar 2 index; the four implementation playbooks are tracked as follow-up work. Resolves #440.
  • Consolidated 9 Learn Monitor daily drift reports (2026-05-27 through 2026-06-04) from bot PRs #343–#383 into main via consolidation PR #385. Superseded PRs closed; data/monitor-state.json updated to newest cumulative state.

Fixed

  • Controls claimed automation the engine never performed (assessment/manifest/generate_manifest.py, controls.json). Control 1.2 published automation: full while only 1 of its 3 checks (agent_inventory_exists) had a registered evaluator — auth_mode_configured and no_orphaned_agents were declared in the manifest but never implemented, so they silently returned unknown while the report implied full automated coverage. Controls 1.8 and 1.10 published automation: partial with zero working evaluators (sentinel_agent_alerts_exist, comm_compliance_policy_exists). All three now follow the repo's established fail-closed shapes: 1.2 drops to partial with 1.2.b/1.2.c converted to explicit manual gates (pass_condition: "" + collection_methods: ["Manual"], mirroring 1.11.b/c) plus a new manual_question covering authentication-mode and orphaned-owner evidence; 1.8 and 1.10 drop to manual with empty checks/collection_methods and (0, 0) zone thresholds (mirroring 1.15), their manual questions extended to absorb the evidence the removed checks claimed to gather. Controls 1.4 and 1.6 were audited in the same pass and confirmed already honest — no change. Because zone_thresholds are derived from the auto-evaluable check count, 1.2's Zone 3 min_checks_passed falls from an unreachable 3 to 1, with the two manual gates capping maturity below the zone target until attested. docs/reference/assessment-coverage.md and docs/javascripts/control-explorer-data.json regenerated accordingly (unimplemented checks 76→72). Resolves judeper/OceanSquad#263.
  • Nine controls claimed "no companion solution" while the pinned solutions lock mapped one (docs/controls/, scripts/verify_solutions_docs.py). Control 1.2 asserted that no companion solution existed, but assessment/manifest/controls.json, assessment/data/solutions-lock.json, and docs/reference/solutions-index.md all mapped it to agent-365-lifecycle-governance — and the companion repository's canonical solutions.json confirms that mapping upstream, so the manifest was right and the control document was wrong. The sentinel even contradicted the solutions-index.md#coverage-scope anchor it linked to. A full 79-control enumeration found the same contradiction in 1.1, 1.2, 1.13, 1.25, 2.6, 2.17, 2.24, 3.7, and 4.3; each now carries an Automation Available block naming the mapped solutions. verify_solutions_docs.py gains a fourth check that fails when a control declares no companion solution while the lock maps one — deliberately a contradiction guard, not a completeness guard, so it neither forces a control to enumerate every mapped solution nor forbids cross-referencing an unmapped one. Covered by 2 new tests (7 total). Resolves judeper/OceanSquad#260.
  • e2e-full was fully broken on main by a Playwright pin skew (.github/workflows/e2e.yml, update-snapshots.yml). A Dependabot minor bump set @playwright/test to 1.61.1 while the pinned container stayed v1.60.0-noble, so all 81 tests failed at browserType.launch. It was invisible at PR time (e2e-full is skipped on PRs; e2e-smoke self-heals via npx playwright install). Bumped both container pins to v1.61.1-noble and added the pin-drift guard (see Added) so the skew cannot silently recur.
  • WCAG 2.1 AA color-contrast violations on customer-facing docs (docs/stylesheets/control-bluf.css, docs/stylesheets/extra.css). Restoring e2e-full un-masked 12 axe color-contrast failures the broken suite had hidden: BLUF metadata labels / +N more chips (#717171#696969), .bluf__action links (an intended #005A9E override that .md-typeset a specificity had been overriding back to #0078D4), homepage job-card links (#0078D4#005A9E on the warm #faf8f5 card surface), and the dark-palette print button (white on #429CE3#005A9E, 7.10:1). Verified 12→0 across both palettes via tests/e2e/32-docs-a11y.spec.mjs.
  • Dead PyRIT install link (docs/playbooks/control-implementations/2.5/portal-walkthrough.md). The …/PyRIT/getting-started/install/ URL returned 404 after PyRIT's documentation reorganization; repointed to the stable repository README. Clears the recurring markdown-link-check (Link Validation) failure on main.
  • Baseline advance could silently advance the wrong URL and lose a real change (scripts/autodoc_advance.py, scripts/autodoc_defer.py, .github/workflows/learn-monitor-advance.yml). The deferred-baseline advance matched a closed autodoc issue to a pending change via GitHub's tokenized {url} in:body search — so a short watchlist URL's tokens could subset an unrelated closed issue, advancing the wrong baseline and deleting a still-open URL's pending blob (silent data loss). It now matches a closed issue to a change by an exact (url, content_hash) identity plumbed end-to-end (detection → report Content-Hash: → contract → Source:/Content-Hash: issue lines, with a fallback to the autodraft tracking issue's JSON contract), only treats issues closed as COMPLETED as terminal, and keys pending blobs by (url, content_hash) so a second change to one URL no longer overwrites/orphans the first. A tribunal owl-review caught and closed a follow-on coverage gap (the parser missing the autodraft tracking-issue format); new regression tests in scripts/test_autodoc_advance.py pin each defect.
  • Regulatory monitor never persisted state, and would have burst on first persist (scripts/regulatory_monitor.py). It called save_state_atomic(STATE_FILE, state) with the arguments swapped (signature is (state, state_path)), raising a TypeError the workflow's continue-on-error swallowed — so the regulatory monitor had never saved state (zero persisted regulatory reports). Fixed the call order (+ a non---dry-run regression test) and added first-run baseline suppression (mirroring learn_monitor) so the first persisted run records the baseline silently instead of flagging ~30 days of items as new.
  • Admin-proof required-check deadlock (.github/workflows/required-check-shims.yml + new required-check-shim-mkdocs.yml, .github/workflows/python-quality.yml). A single shared paths-ignore (the union of two real workflows' paths:) was not an exact complement of either, so a PR touching only e.g. tests/spa/**, playwright.config.mjs, VERSION, or overrides/** triggered neither the real check nor its shim and could never merge (even by an admin). Split into two shims, each paths-ignore mirroring exactly its own real workflow's paths:, and extended python-quality.yml paths (data/**, tests/**, package.json, playwright.config.mjs, overrides/**, …) so the five named quality checks always report. Verified with three throwaway probe PRs (each reached 11/11 required checks).
  • Redirect target host was not validated (scripts/autodoc_runner.py, scripts/autodoc_redirect_ci_verify.py). A poisoned upstream redirect could land an attacker-controlled URL in docs/reference/microsoft-learn-urls.md as a clean single-cell swap. The runner and the independent CI verifier now enforce a fail-closed Microsoft-domain allowlist (learn.microsoft.com / microsoft.com / *.microsoft.com) on the new target host (taken from urlparse().hostname, so credential tricks and subdomain spoofs are rejected); off-domain targets escalate / fail the verifier. Landed before enabling Stage-2 auto-merge anywhere.
  • find_affected_controls under-reported affected files; monitor scripts had no offline smoke test (scripts/monitoring_shared.py, scripts/learn_monitor.py, scripts/regulatory_monitor.py). Adopted from FSI-CopilotGov while making FSI-AgentGov the canonical pipeline: a cross-cutting scan over sibling playbook folders (governance-operations, compliance-and-audit, incident-and-risk, agent-lifecycle) so a detected change reports all affected docs; a true offline --dry-run early-exit; and a new scripts/test_monitor_smoke.py.
  • Autodoc scheduled task runs against a dedicated, auto-synced checkout (scripts/Register-AutodocTask.ps1). The runner reads the latest Learn Monitor report from its checkout, but the monitor publishes reports via a PR that merges to main — so a task pointed at the operator's working tree would only ever see whatever report that tree last had (and the operator actively uses it for feature-branch work, making an in-place git pull unsafe). The registration script now clones a dedicated checkout the task fully owns (-CheckoutPath, default sibling <repo>.autodoc), seeding its idempotency ledger from the operator's repo. Each run the task hard-syncs that checkout to origin/<base> (fetch + checkout + reset --hard, each fail-closed) before invoking the runner, so it always processes the newest merged report — and never touches the operator's branches, working tree, or uncommitted changes. reset --hard leaves untracked files in place, so the ledger persists. To prevent ever hard-resetting the wrong tree, the script only operates on a checkout it created (marked with a .git/autodoc-owned sentinel) and refuses to adopt any pre-existing checkout — robust against path aliases (junctions/symlinks, 8.3 short paths) that a string comparison would miss. Surfaced while wiring up unattended operation after the first supervised live run.
  • Autodoc scheduled-task GitHub auth (scripts/Register-AutodocTask.ps1). The runner uses bare git push origin and gh, which on an EMU-licensed machine resolve to the active EMU account (judep_microsoft) and are denied write access (HTTP 403) — the Windows Credential Manager overrides with the EMU token even when judeper is logged in. The scheduled-task command now authenticates every write as a new -PushAccount parameter (default judeper): at task time it reads that account's token from the gh keyring (gh auth token --user judeperno static secret stored) into GH_TOKEN, and the dedicated checkout's local .git/config routes git's github.com credentials through gh auth git-credential, so git and gh both authenticate with that token. (The credential override lives in the checkout config file rather than GIT_CONFIG_* env vars because the Task Scheduler's Windows PowerShell 5.1 host drops an empty-string env var, which made git report missing config value GIT_CONFIG_VALUE_0; the file-based empty-helper reset works reliably and survives git reset --hard.) Scoped to the dedicated checkout, so the operator's interactive git/gh accounts are untouched. Token resolution is fail-closed: if the keyring token can't be resolved at task time, the task throws before the runner starts (rather than letting GH_TOKEN fall back empty to the denied EMU account). The runbook gains a one-time label-creation prerequisite step (the runner attaches autodoc/escalate labels and fails closed if a label is missing). Surfaced by the first supervised live (non-dry-run) execution.
  • Redirect changes can now pass the verifier (scripts/autodoc_route.py). Redirect autodrafts edit docs/reference/microsoft-learn-urls.md, whose section headings are topic names (Copilot Studio, Microsoft Purview, …) — not the generic control headings the contract assigned, so the deterministic verifier's section_allowlist check blocked every redirect edit and they always escalated. The redirect contract now sets allowed_headings to the target file's own headings (extracted with the same markdown-it-py oracle the verifier uses, so they match exactly); the other five checks (path-allowlist, diff-minimality, claim-support, FSI language, fingerprint) still gate the edit. Fails closed if the file can't be read. Surfaced by a controlled live dry-run.
  • Autodoc runner draft timeout too tight (scripts/autodoc_runner.py). A live Opus draft exploring a fresh ~1,280-file worktree can take 10+ minutes; the 600s default timed out mid-draft (the same change completed under 600s on another run — it sits right at the boundary). Raised the default draft timeout to 1200s (review to 300s) and exposed --draft-timeout / --review-timeout CLI flags for tuning. Surfaced by the second controlled dry-run.
  • Autodoc runner worktree cleanup (scripts/autodoc_runner.py). The per-change finally cleanup ran git checkout --force main inside the disposable linked worktree, which git rejects with fatal: 'main' is already used by worktree … (exit 128) because the base branch is checked out in the primary worktree. It now detaches (git checkout --force --detach main). Found by the first controlled live dry-run (mocked unit tests stub git, so they could not surface it); the draft → deterministic verify → cross-model review path itself worked end-to-end.
  • Replaced non-rendering Material shortcode markup on the homepage quick-start cards (docs/index.md) with plain text labels so GitHub Pages no longer displays literal :material-*: tokens.

Changed

  • Redirect changes are handled deterministically, with no LLM (scripts/autodoc_runner.py). A URL redirect is a mechanical string swap, and the URL list (microsoft-learn-urls.md) stores entries as table rows (| Title | URL | Date |) — so an LLM draft + prose verifier was the wrong tool (it failed claim_support because swapping the URL marks the whole row's title/date as unsupported "new claims"). The runner now detects redirect changes and applies the exact source_url→new-URL replacement itself, verifies the staged diff is a clean URL-only swap confined to the URL list, and opens a human-merge PR — escalating if the URL isn't found, the new URL is already present, the new or old URL contains non-URL-legal/table-breaking characters, the swap isn't clean, or the URLs can't be parsed. In a live dry-run this took ~6 seconds and reached pr_opened (vs ~13 min of flaky LLM drafting that always escalated). No cross-model review is needed (there's no model output to review). The replacement is boundary-aware (a compiled re.escape(old_url) + negative-lookahead on URL-continuation characters), so a redirect of a URL that is a prefix of a sibling (e.g. .../environment-groups vs .../environment-groups-rules) swaps only the exact URL and never corrupts the longer sibling; the same boundary rule guards the "new URL already present" ambiguity check so a sibling prefix does not trigger a spurious escalation. As an independent backstop, the clean-diff guard is structural (table-cell based, not a string replace): every removed row's URL cell must equal the old URL exactly and differ from the matching added row only by that cell becoming the new URL, so a prefix-corrupted sibling is rejected even if the regex had let it through.
  • Autodoc draft + review are faster and Windows-safe (scripts/autodoc_runner.py, scripts/autodoc_cli_review.py). The draft now inlines the current content of the allowed file(s) (capped at 60 KB each) into the prompt and tells the model not to explore the rest of the worktree — cutting a live Opus draft from ~18 min to ~3 min per attempt. Both the draft and the review now pass their (potentially large) prompt to the Copilot CLI via stdin instead of a -p argument, avoiding the Windows command-line length limit (WinError 206). Found while validating the pipeline with controlled live dry-runs.
  • Autodoc pipeline pivots from GitHub's cloud coding agent to a local, unattended GitHub Copilot CLI drafter. GitHub's cloud coding agent cannot drive this pipeline on these repositories: the enterprise Copilot license lives on an EMU account that is barred from the public personal repo, and GitHub disallows cloud-agent automations on public repositories. The drafter is therefore the GitHub Copilot CLI itself (the EMU license provides reasoning; the judeper token performs all repo writes — independent auths), run headless on a schedule, with independent review performed by a different Copilot model family rather than a third-party API. Phase 1 of the pivot (this change): retires the cloud-agent workflows (learn-autodoc-route.yml, autodoc-fix-retry.yml) and the Anthropic LLM verifier (scripts/autodoc_llm_verify.py), and makes the autodoc-verify.yml CI gate deterministic-only (drops the ANTHROPIC_API_KEY dependency). Routing (autodoc_route.py), the deterministic verifier, the canary, the retry/escalation decision logic, and the F5 ledger are all retained. The pipeline remains off by default (AUTODOC_ENABLED).
  • Learn Monitor PRs now self-consolidate and auto-merge (Stage 0 monitoring hardening). .github/workflows/learn-monitor.yml gained two steps after PR creation: (1) close older bot-created monitoring/learn-<n> PRs as superseded (the newest carries the cumulative data/monitor-state.json baseline), and (2) enable squash auto-merge on the new PR once the required checks pass. Safety constraints: PR creation uses add-paths so the branch can only contain data/monitor-state.json(.backup) and reports/monitoring/**; auto-merge re-validates that every changed file matches that allowlist (else it labels needs-review and skips); consolidation closes only PRs carrying the learn-watch label, matching the exact ^monitoring/learn-[0-9]+$ pattern, with a strictly lower run number (never a human PR sharing the prefix); both steps are gated by the LEARN_STATE_AUTOMERGE kill-switch and the workflow runs under a concurrency group. Documented in docs/reference/learn-monitor-guide.md. Addresses the recurring monitoring-PR pile-up (#447).
  • Added explicit Markdown authoring guidance in README.md and CONTRIBUTING.md to avoid :material-*: shortcodes in page content under the current CSP-safe MkDocs emoji configuration.

[1.6.2] — May 11, 2026 (Frontier Readiness auto-evaluator wave)

Release theme: Six-PR wave wiring telemetry-driven auto-scoring for the Frontier Readiness assessment, taking auto-evaluable coverage from 0/25 (0%) to 6/25 (24%). After this release, the Frontier auto-evaluable backlog is structurally exhausted — the remaining 19 questions (76%) are facilitator-only by design (board attestation, written policy text, executive interviews, regulatory committee minutes, business strategy alignment) and cannot be honestly derived from M365/PPAC/Sentinel/SharePoint telemetry.

Upgrade safety: No breaking changes. No control IDs renamed. Schema additions only on the Frontier manifest (six entries flipped to auto_evaluable: true with new notes fields). Assessment engine grows by six evaluator functions plus 21 new tests; existing 78-control assessment behaviour unchanged. Safe to upgrade in place.

Honesty principle: Every evaluator added in this wave is partial-capped — none ever returns "yes". Each Frontier question has at least one facilitator-only sub-claim (governance maturity, written attestation, named executive sponsor) that telemetry cannot verify, so auto-scoring asserts only what telemetry can support and explicitly names the residual facilitator burden in evidence strings. The honest assessment-coverage report at docs/reference/frontier-assessment-coverage.md reflects this structural floor — it is not a roadmap target to "improve."

Coverage progression

Wave PRs Auto Manual % Auto
Pre-evaluators (v1.6.1) 0 25 0%
Q16 + Q17 framework #215, #216 2 23 8%
Q13 partial-cap pattern #218 3 22 12%
Q01 word-boundary regex #219 4 21 16%
Q18 + Q03 closeout #220 6 19 24%

PR #215 — Q16 + Q17 evaluator framework

Established the Frontier evaluator infrastructure: assessment/engine/score_frontier.py with _load_collected_json helper, EVALUATORS registry, compute_evaluator_coverage API, and the first two evaluators:

  • Q16 (zone_classification_present) — pure auto: PPAC environment Tags / Group naming for Zone 1/2/3 classification
  • Q17 (audit_log_retention_meets_finra) — pure auto: M365 audit retention policies via Purview audit-log search export

Coverage matrix infrastructure (docs/reference/frontier-assessment-coverage.md) and CI gating (scripts/generate_coverage_matrix.py --type frontier --check) added in this PR.

PR #216 — PPAC environment-group enrichment

Extended assessment/collectors/Collect-PPAC.ps1 with two new sections:

  • Section 8 — Environment Groups via BAP API (Id, DisplayName, Description, CreatedTime, EnvironmentCount)
  • Section 9 — per-environment tag/group enrichment (EnvironmentGroupId, Tags)

These sections back the 3-way correlation in PR #220 (Q18) and improve Q16's signal precision.

PR #218 — Q13 partial-cap pattern

Q13 (zone_classification_with_audit_supervision_and_model_risk) — established the partial-cap pattern that the rest of the wave inherits. Combines Q16's PPAC zone signal with Q17's audit signal and Purview supervision policy presence. Returns "partial" when telemetry signals are present but caps there because model-risk-management governance attestation is facilitator-only.

Pattern features replicated by Q18 + Q03: - _metadata.errors short-circuit per source - None only when ALL sources unavailable - Evidence string explicitly names every missing signal AND every facilitator-only caveat - NEVER_returns_yes test invariant

PR #219 — Q01 + Graph job-title enumeration

Q01 (ai_initiative_owner_identified) — keyword search over Graph user job titles for AI leadership signals (CDO, Chief AI Officer, Chief AI Risk Officer, VP AI, Head of AI, etc.). Required collector extension:

  • Collect-Graph.ps1 §7 added: AI Leadership Job Titles via two narrow Get-MgUser startswith queries + post-filter (Graph API does not support contains on job-title)

Word-boundary regex (r'\bVP\b', r'\bCDO\b') used for short acronyms to prevent false positives like "VPC" or "CDOs". Capped at "partial" because mere title presence does not confirm active sponsorship.

PR #220 — Q18 + Q03 closeout (this release)

Q18 (env_groups_with_inventory_siem_rag_and_lineage, L300 Tech & Data) — 3-way telemetry correlation across: - PPAC environment groups (Sections 8+9 from #216) - Sentinel SIEM data connectors (Office365Enabled, McasEnabled, TotalConnectors) - SharePoint item-level permission scan (itemLevelPermissions[].SampledItems + groundingCrossRef.ApprovedFound)

Telemetry gap explicitly acknowledged: automated agent inventory is not collected by any current collector. Q18 evidence string names this as "agent inventory not collected (out of scope)" rather than silently degrading. RAG-integrity validation + data lineage documentation are flagged as facilitator-only.

Q03 (enterprise_ai_strategy_published_with_portfolio, L300 AI Strategy & Experience) — SharePoint site-name heuristic against 8 multi-word strategic keywords (ai strategy, ai governance, ai council, ai portfolio, agent portfolio, frontier, executive sponsor, governance committee). All keywords are multi-word so plain substring matching avoids the false-positive risk that Q01 had to navigate for short acronyms. Capped at "partial" because "published" is telemetry-verifiable but "with portfolio" + "active governance" are facilitator-only.

Generator update: scripts/generate_coverage_matrix.py _FRONTIER_EVALUATOR_CANDIDATES list emptied — Q03 + Q18 removed because they are no longer "future." The list is now structurally complete; any new Frontier evaluator wiring would require an explicit governance decision to relax the facilitator-only floor.

Test additions across the wave

  • v1.6.1 baseline: 72 tests
  • After #215: 81 tests (+9 for Q16 + Q17)
  • After #218: 85 tests (+4 for Q13)
  • After #219: 93 tests (+8 for Q01)
  • After #220: 114 tests (+21 for Q18 + Q03) — release-time count for v1.6.2 PR-wave-220
  • Current suite (post-release additions): 140 tests (verified 2026-05-16)

All six evaluators ship with NEVER_returns_yes invariant tests, evidence-string assertions, and facilitator-override (driver-level upgrade/downgrade) tests.

Validation gates (all six PRs)

Every PR in this wave passed the full gauntlet locally and in CI:

  • pytest assessment/tests/ -q
  • ruff check assessment scripts
  • generate_coverage_matrix.py --type frontier --check
  • generate_coverage_matrix.py --check (78-control assessment)
  • check_manifest_doc_drift.py --check
  • verify_language_rules.py

PowerShell static analysis (PSScriptAnalyzer) gated PR #216 (collector changes). All other PRs were Python-only.

Files changed (cumulative across the wave)

  • assessment/engine/score_frontier.py — new module, 6 evaluators + helpers + EVALUATORS registry
  • assessment/manifest/frontier-readiness.json — 6 entries flipped auto_evaluable: true with notes
  • assessment/tests/test_score_frontier.py — 6 evaluator test classes (~1300 lines)
  • assessment/tests/fixtures/ — 14+ new fixtures (PPAC env-group variants, Sentinel connector variants, SharePoint variants)
  • assessment/collectors/Collect-PPAC.ps1 — Sections 8+9 added (#216)
  • assessment/collectors/Collect-Graph.ps1 — Section 7 added (#219)
  • docs/reference/frontier-assessment-coverage.md — auto-regenerated; final state 6/25 (24%) Auto, 19/25 (76%) Manual, 0 Unimplemented
  • scripts/generate_coverage_matrix.py--type frontier mode + _FRONTIER_EVALUATOR_CANDIDATES retired

Forward-looking note

The Frontier auto-evaluable backlog is closed. Future Frontier work belongs in three categories:

  1. Facilitator playbooks — published guidance on how to evidence the 19 facilitator-only questions during an actual Frontier engagement
  2. Driver/pattern coverage docs — narrative guidance mapping each Frontier transformation pattern to which controls in the 78-control framework it leans on
  3. Telemetry honesty maintenance — keeping the 6 existing evaluators current as collectors evolve (e.g., if Microsoft adds an "agent inventory" Graph endpoint, Q18's evidence string would need an update)

No further Frontier evaluator wiring is planned. The 76% manual floor is a feature, not a defect.

Post-release triage fix cycle (2026-05-17)

Triage of 3 independent external audits (51 unified findings + 8 rubber-duck additions = 59 total). 12 PRs merged on 2026-05-17. No VERSION bump — fixes stay under v1.6.2.

Regulatory correctness - PR-3 (#273): Added SR 26-2 / OCC 2026-13 generative-AI scope caveat to docs/reference/regulatory-mappings.md and docs/framework/regulatory-framework.md. The interagency MRM guidance issued April 17, 2026 explicitly excludes generative AI and agentic AI from scope per primary-source verification. Re-characterized GenAI-specific control mappings (Controls 2.11, 2.16, 2.20, 3.10) as analogous principles rather than direct regulatory obligations. - PR-4 (#280): Added NAIC Model Bulletin on Use of AI by Insurance Companies (December 2023), NFA Compliance Rule 2-9 (FCM/IB/CPO/CTA supervisory baseline), SEC Regulation S-P (including the May 2024 30-day NPI notification amendments). Upgraded NYDFS Part 500 surfacing in regulatory-framework.md. Added OCC Bulletin 2023-17 number to existing Interagency Third-Party Guidance citations. - PR-6 (#281): Resolved 624 sector-specific TODO placeholders in assessment/manifest/controls.json (replaced with null per schema preservation). Canonicalized 61 stale OCC-2011-12 / Fed-SR-11-7 machine-readable codes to OCC-2026-13 / Fed-SR-26-2.

Assessment engine - PR-5 (#276): Fixed 8 of 11 evaluator drift (6 manifest pass_condition strings rewired, 2 preserved for future wiring). Added collector payload normalization layer in score.py. Regenerated frontier-assessment-coverage.md (correctly shows 6/25 = 24% — previously stale at 0%). Documented SPA vs Python engine semantic divergence in assessment/README.md and docs/assessment/index.md. Auto-evaluable controls: 1/78 → 7/78.

Customer-facing surfaces - PR-1 (#271): Fixed count drift on home page (5 → 6 Regulatory Frameworks) + Solutions Integration repo-structure block + Summary Statistics block. - PR-2 (#275): ~240 playbook footer canonicalizations + 6 stale non-playbook stamps brought to canonical v1.6.2 / May 2026. - PR-7 (#274): Refreshed all 6 Excel templates from v1.4.0 — April 2026 to v1.6.2 — May 2026. Restored 20 dashboard rollup formulas (governance-maturity-dashboard.xlsx). Added missing controls 2.26 / 1.29 / 4.8 / 4.9 to docs/downloads/index.md. Hardened scripts/verify_excel_templates.py. - PR-8 (#279): Corrected Control 1.1 SEC 17a-4(f) overclaim to align with Control 1.7's capture-vs-preservation framing. Removed duplicate AIAppInteraction bullet from Control 1.7. - PR-11 (#270): Corrected static SVG pillar counts in solutions-integration-overview.svg (28/24/12/7 → 29/26/14/9). - PR-13 (#269): Replaced 2 redirecting Microsoft Learn URLs across 8 files. - PR-15 (#282): Final footer cleanup on 7 top-level customer-facing pages that PR-2's playbook-scoped sweep didn't reach.

Hygiene - PR-14 (#272): Clarified CHANGELOG.md test-count narrative (114 release-time vs 140 current). Also added CHANGELOG.md to python-quality.yml paths trigger so changelog-only PRs satisfy branch protection.

Companion repository (FSI-AgentGov-Solutions) - 5 GitHub issues drafted and posted at #143–#147 for future work (MRM Automation regulatory refresh, solutions inventory reconciliation, version drift between site and repo, preview-vs-live status, canonical control-coverage metadata export).

Audit artifacts (private, gitignored) - All 3 external audits + 12 verification tracks + 8 enumeration follow-ups + Phase 3 rubber-duck critique + unified findings register (59 findings) + fix plan + final QA + handoff brief stored in maintainers-local/audits/2026-05-16/ for internal record.

Net findings disposition: 30 confirmed-fixed / 13 rejected (audits read stale corpus state) / 9 deferred-informational / 7 pending external Microsoft product-surface research.

Pending user actions (not blocking customer handoff) - Forward 7 Microsoft product-surface researcher prompts to specialized researcher (maintainers-local/audits/2026-05-16/findings/track-j-msft-research-prompts.md) - Review 5 companion-repo issues #143–#147 in FSI-AgentGov-Solutions


[1.6.1] — May 10, 2026 (Microsoft Learn drift patch)

Release theme: Documentation-only patch responding to upstream Microsoft Learn changes detected by the Learn Monitor (run 114, 2026-05-10). Five follow-up issues were filed (#205–#209); four resulted in doc updates; one (#205) was investigated and closed not planned (the framework had never adopted the deprecated terminology). Five parallel Sonnet agents in five git worktrees executed the fixes simultaneously, validating the worktree-per-agent pattern at scale.

Upgrade safety: No breaking changes. No schema changes. No control IDs renamed. No file additions. Pure documentation patches across 5 controls + 5 playbooks + license-requirements.md. Safe to upgrade in place.

Issue #206 — Analytics retention + 7-area effectiveness (#211, 3a936123)

Modified:

  • docs/controls/pillar-3-reporting/3.2-usage-analytics-and-activity-monitoring.md — Data Availability info box: 180-day analytics, 28-day session details
  • docs/controls/pillar-2-management/2.5-testing-validation-and-quality-assurance.md — retention windows admonition
  • docs/controls/pillar-2-management/2.6-model-risk-management-sr-26-2.md — retention admonition in §Platform-Enabled Monitoring; footer to May 2026
  • docs/controls/pillar-2-management/2.9-agent-performance-monitoring-and-optimization.md — retention admonition in §Verification Criteria
  • docs/controls/pillar-3-reporting/3.10-hallucination-feedback-loop.md — retention admonition after Feedback Capture table
  • docs/playbooks/control-implementations/2.5/portal-walkthrough.md — new §9.8 covering 7-area effectiveness panel structure (added "Knowledge source use")
  • docs/playbooks/control-implementations/2.6/portal-walkthrough.md — retention admonition in §3.1

Net change: +49 / −4 lines.

Issue #207 — IRM DLP workload caveats + role groups (#212, 7a026bb1)

Modified:

  • docs/controls/pillar-1-security/1.12-insider-risk-detection-and-response.md!!! warning "IRM DLP workload limitations" admonition listing 5 unsupported workloads (Teams, Endpoint DLP, M365 Copilot, Power BI, on-premises repositories); 3 verbatim role groups cited from Microsoft Learn (Insider Risk Management, Insider Risk Management Analysts, Insider Risk Management Investigators); cross-references to controls 1.5, 1.6, 1.10, 1.13
  • docs/playbooks/control-implementations/1.12/portal-walkthrough.md — workload caveat surfaced in walkthrough

Net change: +72 / −2 lines.

Issue #208 — BCDR retention defaults + RPO/RTO surfacing (#213, 8cb6bbec)

Modified:

  • docs/controls/pillar-2-management/2.4-business-continuity-and-disaster-recovery.md — retention table corrected: 7-day default ALL environments; extended retention up to 28 days requires production Managed Environments. Surfaces RPO/RTO from new Microsoft FAQ: within-region near-zero RPO + <5min RTO; cross-region typical replication lag <15min
  • docs/playbooks/control-implementations/2.4/portal-walkthrough.md — retention defaults aligned
  • docs/playbooks/control-implementations/2.4/troubleshooting.md — footer
  • docs/images/2.4/EXPECTED.md — screenshot specs aligned to new defaults

Net change: +25 / −15 lines.

Issue #209 — Agent 365 license deadline 2026-07-01 (#214, cbfbb463)

Modified:

  • docs/controls/pillar-1-security/1.8-runtime-protection-and-external-threat-detection.md!!! danger deadline callout: AI Agent Inventory in Defender for Cloud Apps requires Agent 365 after 2026-07-01; orgs without Agent 365 lose AI Agent Inventory visibility entirely
  • docs/controls/pillar-3-reporting/3.7-ppac-security-posture-assessment.md — deadline callout for Defender for Cloud Apps cross-reference (walkthrough Step 8)
  • docs/playbooks/control-implementations/1.8/portal-walkthrough.md — danger admonition in walkthrough
  • docs/playbooks/control-implementations/3.7/portal-walkthrough.md — danger admonition in walkthrough
  • docs/reference/license-requirements.md — two new rows for controls 1.8 / 3.7 documenting the Agent 365 transition

Net change: +60 / −10 lines.

Issue #205 — Sensitivity labels Entra group classification migration (closed not planned)

Investigated, no changes required. Exhaustive grep across the entire framework for Entra group classification, Convert Entra group classification, Classic Azure AD classification, and Convert classic group classifications returned zero matches. The framework had never adopted the deprecated terminology. Three classification-adjacent terms (DLP connector classification, Entra group membership for DLP scoping, SharePoint classic sites) were verified unrelated. Issue closed with audit comment; branch never pushed.

Workflow validation

  • 5 parallel Sonnet agents in 5 git worktrees — zero filesystem race conditions, zero merge conflicts, all 5 agents independently ran mkdocs build --strict against the same global Python install with no contention. Wall time per agent: 9–12 minutes.
  • Empty-commit pattern (#205) — agent created an audit-trail commit when investigation found nothing to fix; orchestrator chose to skip the empty PR and close the issue directly with the investigation comment instead.
  • CI gates per PR — 8/8 required checks green (mkdocs --strict, verify_language_rules, verify_controls, drift, coverage matrix, ruff, pytest, codeql) before merge.

Hard rules

  • Tier-1 banlist enforced — 0 banned-phrase hits across all 4 PRs.
  • 78-control catalog unchanged. Pillar structure unchanged. Zone model unchanged.
  • No manifest changes. controls.json byte-identical to v1.6.0.
  • No solutions catalog changes. Companion repo untouched.
  • Documentation-only patch. No code changes to assessment/, scripts/, or workflows.

Validation at release

Gate Result
mkdocs build --strict 0 warnings
verify_language_rules.py 0 banned phrases
verify_controls.py 78 controls pass
check_manifest_doc_drift.py --check 78=78=78
generate_coverage_matrix.py --check current
generate_pattern_coverage.py --check (with companion repo) current (78 controls, 35 solutions)
ruff check all pass
pytest assessment/tests/ 56 passed

[1.6.0] — May 10, 2026 (Solutions Discoverability Release)

Release theme: Make the 35 companion solutions discoverable by Microsoft CAPE alignment metadata. Phase 6a tagged every solution README in the companion repo with applicable_patterns, applicable_drivers, and coe_function frontmatter; Phase 6b consumed those tags in the framework repo to enrich the Solutions Index and the Pattern Coverage matrix. No control catalog changes; no schema changes.

Upgrade safety: No breaking changes. No control IDs renamed. No controls.json schema changes. Safe to upgrade in place. Existing Solutions Index consumers that grep on existing column headers continue to work — three new columns (Patterns, Drivers, CoE) were appended before Summary.

Phase 6a — Companion repo tagging (judeper/FSI-AgentGov-Solutions #134, d1d6f653)

Added (in companion repo):

  • YAML frontmatter on all 35 production solution READMEs with applicable_patterns (subset of P1–P6), applicable_drivers (subset of the 5 canonical Capability Drivers, snake_case IDs), and coe_function (one of govern / enable / optimize / scale)
  • Tag derivation: applicable_patterns from pattern_critical field in framework controls.json for each solution's primary controls (with purpose-based inference where pattern_critical was empty across all primary controls); applicable_drivers from union of primary controls' applicable_drivers; coe_function mapped per agentic-coe.md definitions
  • 282 frontmatter insertions across 35 files; zero README content changes
  • Distribution: govern=20, optimize=8, enable=4, scale=2

Phase 6b — Framework repo consumption (#210, 45dd2cfc)

Added:

  • docs/reference/solutions-index.md — three new columns (Patterns, Drivers, CoE) on the 35-solution table; same fields added to per-solution detail blocks; new "Discovering by CAPE alignment" intro section linking to framework documents
  • docs/reference/pattern-coverage.md — regenerated with new Solutions count column on the coverage summary and a new "Solutions per pattern" section listing all 84 pattern declarations across the 35 solutions

Modified:

  • scripts/generate_pattern_coverage.py — new --solutions-repo CLI flag (also honors $FSI_SOLUTIONS_REPO env var) for parsing companion repo frontmatter via pyyaml; graceful skip when companion repo unavailable
  • .github/workflows/python-quality.yml — new drift step clones companion repo and runs generate_pattern_coverage.py --check to keep pattern-coverage.md in sync with companion frontmatter
  • CHANGELOG.md — this entry

Solutions count per pattern

Pattern Solutions
P1 — Employee AI Enablement 14
P2 — Business Expert Empowerment 9
P3 — Workplace & IT Services 5
P4 — Core Business Process Transformation 25
P5 — External Engagement 19
P6 — AI-First Capabilities 12
Total declarations 84

Hard rules and brand boundary

  • Tier-1 banlist enforced — "ensures compliance", "guarantees", "will prevent", "eliminates risk" remain banned across all docs (0 hits at release).
  • No control IDs renamed, no manifest schema breaks. controls.json unchanged from v1.5.0.
  • 78-control catalog unchanged. Pillar structure unchanged. Zone model unchanged.
  • Companion repo as authoritative source — Pattern/Driver/CoE assignments live in companion repo READMEs; framework repo regenerates pattern-coverage.md from those tags via CI gate. Single source of truth.

Validation at release

Gate Result
mkdocs build --strict 0 warnings
verify_language_rules.py 0 banned phrases
verify_controls.py 78 controls pass
check_manifest_doc_drift.py --check 78=78=78
generate_coverage_matrix.py --check (controls + frontier) current
generate_pattern_coverage.py --check (with companion repo) current (78 controls, 35 solutions)
ruff check all pass
pytest assessment/tests/ 56 passed

[1.5.0] — May 10, 2026 (Microsoft Alignment Release)

Release theme: FSI translation layer for Microsoft CAPE (Copilot Acceleration Engineering) materials. Adds vocabulary crosswalks, framework layer for CAPE concepts, assessment-engine support for CAPE Frontier Readiness scoring, and partner-facing reference docs (CSA + diagram catalog) — all as additive, non-breaking content.

Upgrade safety: No breaking changes. No schema breaks. No control IDs renamed. Safe to upgrade in place. Existing controls.json schema is backward-compatible (only field additions). Existing assessment runs continue to work; CAPE Frontier scoring is opt-in via new -AssessmentType parameter.

Phase 1 — Reference layer (#199, f3e8edc4)

Added:

  • docs/reference/microsoft-cape-crosswalk.md — bridge document mapping the 6 CAPE patterns to FSI controls and regulatory exposure per pattern
  • docs/reference/cco-quick-reference.md — pocket lookup for compliance officers

Modified:

  • docs/framework/regulatory-framework.md — CAPE pattern annotations
  • docs/reference/glossary.md — CAPE vocabulary additions
  • docs/reference/role-catalog.md — expanded role entries
  • scripts/verify_language_rules.py — added Tier-2 banlist (CAPE vendor-marketing language) with <!-- verify-language-rules: allow-second-tier --> CSA annotation support

Phase 2 — Framework layer (#201, 429ab90c)

Added:

  • docs/framework/transformation-patterns.md — canonical 6-pattern framework summary with Pattern 6 D3 guardrail
  • docs/framework/agentic-capability-drivers.md — Microsoft's 5 Capability Drivers and maturity model
  • docs/framework/agentic-coe.md — standalone CoE blueprint with 4 functions (Govern/Enable/Optimize/Scale), CoE shapes, anti-patterns, and federation guardrail

Modified:

  • docs/framework/agent-lifecycle.md, governance-fundamentals.md, index.md, operating-model.md — CAPE concept integration and cross-references
  • docs/reference/microsoft-cape-crosswalk.md — Phase 2 additions
  • docs/reference/role-catalog.md — CoE role additions

Phase 3 — Assessment integration (#202, 0adf51df)

Added:

  • assessment/manifest/frontier-readiness.json — 25 questions × 5 drivers × 5 maturity levels
  • assessment/engine/score_frontier.py — full Frontier Readiness scoring algorithm
  • assessment/collectors/Collect-Frontier.ps1 — interactive + batch collector
  • assessment/tests/test_score_frontier.py — 30 tests (56 total green at release)
  • docs/reference/pattern-coverage.md — 78×6 generated control × pattern matrix
  • docs/reference/frontier-assessment-coverage.md — honest coverage report (0% auto v1; all Frontier scoring is manual-questionnaire-driven)
  • scripts/generate_pattern_coverage.py — coverage matrix generator

Modified:

  • assessment/manifest/controls.json — 78 controls tagged with applicable_drivers, applicable_patterns, pattern_critical (additive fields; backward-compatible)
  • assessment/engine/report.py — added --type controls|frontier|both flag with new report generators
  • assessment/run-assessment.ps1 — added -AssessmentType and -FrontierAnswersFile parameters
  • assessment/README.md — decision tree, Frontier Quick Start, maturity scale
  • scripts/generate_coverage_matrix.py — added --type controls|frontier flag

Phase 4 — Partner-facing reference (#203, 294ae358)

Added:

  • docs/reference/csa-quick-reference.md — Microsoft FSI CSA pocket lookup (197 lines)
  • docs/reference/csa-positioning-guide.md — long-form CSA positioning narrative (390 lines)

Phase 5 — Diagrams + Release closeout (this release)

Added:

  • 5 net-new Mermaid diagrams embedded in framework and reference docs: Pattern × Zone matrix, CoE structure by pattern, Decision rights framework, CAPE 90-day × FSI Phase timeline, Agent lifecycle 7-stage
  • docs/reference/diagram-catalog.md — catalog of all repo diagrams (60+ existing + 5 new) with audience, use-case, and format columns
  • docs/images/diagrams/source/cape/*.mmd — editable Mermaid source files for CSA customer-deck export
  • CHANGELOG.md — this entry

Hard rules and brand boundary

This release adopts CAPE vocabulary as a translation layer, not as endorsement. FSI-AgentGov remains an independent FSI governance framework. Microsoft is not a publisher, sponsor, or reviewer of this content.

  • Tier-1 banlist enforced — "ensures compliance", "guarantees", "will prevent", "eliminates risk" remain banned across all docs (0 hits at release).
  • Tier-2 banlist (CAPE vendor-marketing language: "self-improving", "autonomous decision-making", etc.) is suspended only inside CSA-facing reference docs via the <!-- verify-language-rules: allow-second-tier --> annotation, where CSAs need to teach customers to reframe the language.
  • Pattern 6 D3 guardrail and Federation guardrail appear verbatim in all partner-facing reference docs.
  • No control IDs renamed, no manifest schema breaks. controls.json gained 3 additive fields (applicable_drivers, applicable_patterns, pattern_critical).
  • 78-control catalog unchanged. Pillar structure unchanged. Zone model unchanged.

Validation at release

Gate Result
mkdocs build --strict 0 warnings
verify_language_rules.py 0 banned phrases
verify_controls.py 78 controls pass
check_manifest_doc_drift.py --check 78=78=78
generate_coverage_matrix.py --check (controls + frontier) current
generate_pattern_coverage.py --check current
ruff check all pass
pytest assessment/tests/ 56 passed

[1.4.2] — April 30, 2026 (Phase B′ Triage Fixes)

Patch release closing out the three P2 items deferred from v1.4.1. Markdown export customer header now escapes special characters so admin-entered names render correctly in raw source (#168); the vendored xlsx.full.min.js is marked binary in .gitattributes so Windows checkouts no longer flip its SRI hash via CRLF normalization (#169); and two locally-flaky Playwright specs (14-fetch-failure, 28-perf-budget) are hardened with deterministic ordering and a more realistic perf threshold (#170). Phase B″ triage report (#171) confirmed 0 P0/P1 findings — recommended ship. See CHANGELOG-v1.4.md for the full entry.


[1.4.1] — April 30, 2026 (E2E Test Infrastructure & SPA Hardening)

Quality + assurance release. No control catalog changes. Ships an end-to-end Playwright test suite (~60 specs across smoke, regression, edge cases, accessibility, and production probes), 4 new CI workflows (including SheetJS supply-chain SRI verification and post-deploy production smoke), branch protection as code, and 12+ assessment SPA hardening fixes covering saved-list integrity, storage quotas, formula-injection defenses, prototype-pollution guards, CSP allowlist enforcement, and per-assessment filter namespacing. See CHANGELOG-v1.4.md for the full entry.


[1.4.0] — April 2026 (Assessment Tool Unification & Solutions Bridge)

Added

  • Unified manifest schema: Single source of truth (assessment/manifest/controls.json) for Python scoring engine and assessment SPA with 11 additive fields per control
  • Solutions bridge: Cross-repository integration with FSI-AgentGov-Solutions v1.4.0 via committed solutions-lock.json (35 solutions indexed)
  • 10 SPA enhancements: How-to-verify drawer (E1), zone auto-exclusion (E2), collector evidence import (E3), role filter (E4), sector calibration for 8 institution types (E5), priority starter set of 5 foundation controls (E6), Next Session Agenda export (E7), inline evidence/notes capture (E8), facilitator mode with hints and time budgets (E9), 7 per-role pre-session homework pages (E10)
  • Harvest script: scripts/harvest_manifest_extension.py scaffolds v1.4 fields from existing control docs with TODO placeholders for author-judgment content
  • 3 validators: Manifest schema validator, solutions lock validator, and lock refresh script with tag pinning
  • Portal export envelope (v1.4.1-prep, additive): SPA exportJSON and exportRoleSection now emit a _metadata block (framework version, export schema version, manifest commit hint, pillar names, schema type) plus _computedScores (pillar/overall percentages and counts) and a derived assessmentStatus enum (draft/in-progress/final). Existing top-level state keys are preserved, so v1.3.x consumers continue to work unchanged. Importer silently drops snapshot fields and recomputes on next export. See CHANGELOG-v1.4.md and assessment/data/README.md.

Changed

  • Control count normalization: Fixed stale "71 controls" / "72 controls" references to "78 controls" across all documentation
  • Version bump: 1.3.3 → 1.4.0 across README, mkdocs.yml, CITATION.cff, and meta references

Breaking Changes

  • Assessment SPA export schema: JSON export format incompatible with v1.3.x—no migration tool provided; recommend completing in-progress v1.3 assessments before upgrading or re-running from scratch with v1.4 collector import

Version Period File
v1.6.x (current) May 2026 CHANGELOG.md
v1.5.x May 2026 CHANGELOG.md
v1.4.x April 2026 CHANGELOG-v1.4.md
v1.3.x March–April 2026 CHANGELOG-v1.3.md
v1.1.x December 2025 CHANGELOG-v1.1.md
v1.2.x and earlier October 2025 – March 2026 Archived — see git history prior to April 2026