* docs: trim agent instructions to repository-specific essentials
Consolidate overlapping guidance, correct stale contracts and testing policy, and preserve scoped Excel safety and release requirements.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* docs: preserve detailed guidance in contributor documentation
Move useful examples and authoring procedures out of automatic instructions into their general guides; correct stale contributor guidance and retain short discovery links.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* docs: single-source feature overview and refine commit checks
Generate the website overview from FEATURES.md. Keep validation-only commits out of release packaging while preserving build and count checks, and retain the original output when packaging fails.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Stefan Broenner <stbrnner@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(docs): report real page dates in the sitemap, assert accessibility fixes
The sitemap carried no <lastmod> at all. hooks.py stripped every value with a
regex over the built XML, because MkDocs stamps the *build* date on each URL --
which told crawlers all 52 pages changed on every deploy. Removing them avoided
the false signal but replaced it with no signal.
Dates now come from git: one `git log` walk maps each tracked path to its last
commit, and a wrapper page takes the newest date among itself and the canonical
repo file it mirrors. Verified against `git log -1` for five paths across all
four source layouts.
That let the sitemap become a real template. overrides/sitemap.xml renders both
<lastmod> and the home page's <video:video> block declaratively, replacing ~55
lines of regex surgery plus a manual re-gzip in on_post_build. MkDocs now writes
sitemap.xml.gz from the same rendered output, so the two cannot diverge.
Same treatment for two of the three accessibility patches: the logo (alt="logo",
no dimensions) and the progress bar (role=progressbar with no accessible name)
are now overrides/partials/, since upstream ships them as a 7-line and a 1-line
template. The search dialog stays a string patch on purpose -- Material's search
partial is ~45 lines of markup, icon lookups and feature flags, so forking it to
add one attribute would pin a large slice of theme internals.
None of these were verified before. audit_site.py now asserts all four in the
built HTML, so a Material upgrade that renames a class fails the build instead
of silently regressing accessibility, and asserts every URL has a valid,
non-uniform <lastmod>.
Both workflows that build the site check out with fetch-depth: 0, because a
shallow clone dates every page to the tip commit.
Verification:
- Negative-tested every new guard. Stripped lastmod, uniform dates and a
malformed date each exit 1 with the right message; rebuilding with the
overrides removed and the search patch disabled produces 208 failures
(4 per page x 52).
- That exercise caught a bug in the a11y guard itself (`for ... = checks`
instead of `in`), which had made the check a no-op.
- It also disproved a heuristic I had written: a shallow clone lists all 843
tracked files under one date, so the "few paths means shallow" test never
fires. Replaced with `git rev-parse --is-shallow-repository`, verified True
against a real depth-1 clone and False here.
- Only HTML delta versus the previous build is the minifier dropping quotes
around the logo's src/width/height, which hooks.py used to re-add after
minification. Semantically identical.
- mkdocs build --strict --clean, audit_site.py (52 pages) and
check_deploy_paths.py all pass; 166 files.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 388229c1-868a-416f-8b0a-7d6ee058e788
* fix(docs): match the a11y audit to the elements it actually patches
Copilot review raised two problems with audit_accessibility, both real.
The checks matched any <div role=dialog> / <div role=progressbar> rather than
the specific Material elements the build patches. That fails the wrong way in
both directions: an unrelated dialog Material grows later would fail the build
even though nothing we patch regressed, and - worse - if an upgrade restructured
the search markup out from under the patch, the role-based search would find
nothing and pass silently. Absence was indistinguishable from success, which is
the exact failure mode the audit exists to prevent.
Both now match on the Material class we patch (md-search, md-progress), and an
element that cannot be found is an explicit failure rather than a quiet skip.
Measured first: every built page carries exactly one md-search, one md-progress
and two logo images, so requiring at least one of each is safe.
Verified both of the reported cases:
- Renaming md-search and dropping the aria-label now fails with "no search
dialog found" instead of passing.
- Injecting an unrelated unlabelled <div role=dialog> no longer fails the build.
- Removing both overrides and disabling the search patch still produces the
original 208 failures, and a clean build still passes at 52 pages.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 388229c1-868a-416f-8b0a-7d6ee058e788
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 388229c1-868a-416f-8b0a-7d6ee058e788
* ci(docs): validate the Pages site on PRs and harden the build
The docs site was validated by nothing before merge: CI Gate never built
it, and pre-commit.ps1 classifies gh-pages/ as doc-only. A broken site was
only discoverable after it had already deployed.
Validation
- New "Docs Site" CI job: mkdocs build --strict, audit_site.py and the new
check_deploy_paths.py on every pull request.
- check_deploy_paths.py proves the deploy workflow paths: filter covers
every source hooks.py mirrors. That filter was hand-maintained, so a new
mirrored file silently stopped triggering a deploy.
- Dependabot pip entry for gh-pages: mkdocs-material was never updating.
Build fixes
- hooks.py wrote its generated pages into docs_dir, which mkdocs serve
watches, so every build retriggered itself and looped forever. Generated
output moved to gh-pages/_generated/ with snippets base_path extended to
match. Rebuild detections after one edit: 9+ -> 1.
- Added a watch: key so serve reloads on FEATURES.md, CHANGELOG.md, docs/
and skills/ instead of only on gh-pages/.
Workflow split
- Persisting the star history needs contents: write, and it shared a job
with pip install -r requirements.txt. Split into star-history.yml; the
Pages build is now contents: read and only renders the chart. The
generator tests also run on pull requests now, not just after merge.
- New link-check.yml runs lychee weekly over the built site and files an
issue on link rot. Scheduled rather than per-PR because external
endpoints rate-limit and would make it flaky.
Site output is byte-identical across all 164 files.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 388229c1-868a-416f-8b0a-7d6ee058e788
* fix(docs): keep excluding the former docs/_generated/ location
Moving generated output out of docs_dir also removed the exclude_docs
entry, so a stale docs/_generated/ left in a long-lived clone was silently
built and published as real pages: reproduced at 52 pages instead of 51,
with audit_site.py passing.
Restore the exclusion and keep the old .gitignore entry so the leftover
directory neither gets published nor shows up as untracked.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 388229c1-868a-416f-8b0a-7d6ee058e788
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 388229c1-868a-416f-8b0a-7d6ee058e788
* Initial plan
* fix: accept bool/int args for conditionalformat add-rule over MCP
Co-authored-by: sbroenne <3026464+sbroenne@users.noreply.github.com>
* ci: run Excel-dependent smoke tests on self-hosted Windows Excel runner
Co-authored-by: sbroenne <3026464+sbroenne@users.noreply.github.com>
* ci: fix stale note about smoke tests not running in CI
Co-authored-by: sbroenne <3026464+sbroenne@users.noreply.github.com>
* fix: harden conditional formatting and local E2E
Validate conditional-format rule arguments, release Border COM objects, and verify typed bool/int arguments through CLI and MCP workflows. Retire the Azure Excel runner and replace it with explicit local integration and E2E attestations.
Tests: Release build (0 warnings); ConditionalFormat 27/27; CLI E2E 12/12; MCP E2E 1/1; COM leak and documentation count checks passed.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b7375555-1096-40ae-92a3-2b76383e7934
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sbroenne <3026464+sbroenne@users.noreply.github.com>
Co-authored-by: sbroenne <stefan_broenner@yahoo.com>
Copilot-Session: b7375555-1096-40ae-92a3-2b76383e7934
This is a scratch verification commit for the release-automation fix in
PR #739 (direct changelog push using RELEASE_PAT as a ruleset bypass
actor). It will be reverted immediately by a follow-up commit.
* ci: add required CI Gate, remove stale/superseded workflows
Consolidate PR validation into a single always-running 'CI Gate' workflow
(.github/workflows/ci.yml) that ports the Excel-free pre-commit gates so they
are enforced server-side even if the local hook is bypassed:
- Release build (compile + source generators)
- COM-leak, success-flag, coverage/naming, MCP-Core, doc-counts, dynamic-cast,
plugin-README audits
- Excel-free CLI --help and MCP Server build smoke + artifact upload
Excel-dependent gates (CLI workflow smoke, MCP smoke, integration tests) are
NOT run in CI - GitHub runners have no Excel - and remain local-only.
Also:
- Remove superseded Build CLI / Build MCP Server workflows (absorbed by CI Gate;
fixes the missing pull_request trigger on the MCP build)
- Remove stale.yml (stale-issues automation)
- Drop the dead 'develop' push trigger from CodeQL (branch does not exist)
- Add .github/CODEOWNERS (routing only)
- Document that the CI Gate mirrors the Excel-free gates
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a1546dd0-9bc6-46a6-8648-e700b0bcc8bf
* docs: point workflow references at consolidated CI Gate
Update README badges, PRE-COMMIT-SETUP.md, and development-workflow
instructions to reference ci.yml (CI Gate) instead of the removed
build-cli.yml / build-mcp-server.yml workflows. Addresses Copilot PR
review feedback on #715.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a1546dd0-9bc6-46a6-8648-e700b0bcc8bf
* ci: drop brittle gate/rule number citations in CI Gate step labels
Release build comment referenced 'pre-commit gate 6' and the dynamic-cast
step was labeled 'Rule 14'; both cross-references were inaccurate (gate
numbering differs between pre-commit.ps1 and the instructions table, and
Rule 14 is unrelated). Describe the steps instead. Addresses Copilot
review feedback on #715.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a1546dd0-9bc6-46a6-8648-e700b0bcc8bf
---------
Co-authored-by: Stefan Broenner <stbrnner@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>