Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/agent-memory/task-researcher/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
- [legacy-scodictionary-removal-315](project_legacy_scodictionary_removal_315.md) — #315: DELETE SCODictionary_Tests(+Additional), RETARGET 3 SmartSerializable* test files, IScoDictionary interface safe to keep for F5 (2026-07-11)
- [lock-recursion-coverage-317](project_lock_recursion_coverage_317.md) — #317: deleted LockRecursionTests.cs is a restoration (F2-authored clean-base coverage F5 knowingly removed per WI-4), not new authoring; no git/shell tool this session (2026-07-11)
- [qfc-folder-tree-percentage-325](project_qfc_folder_tree_percentage_325.md) — #325 (epic child 9003): only 1 live viewer (ItemViewer) despite 9 dead CboFolders variants; owner-draw ComboBox + host-neutral TreeNode<T> seams; consumes 9001 probability contract (2026-07-15)
- [dependabot-net481-340](project_dependabot_net481_340.md) — #340: no packages.config package currently dropped net481; transitive-bump restraint is already Dependabot's NuGet default (cite security-updates docs, not a new config primitive); use semver-major ignore not fabricated version ceilings (2026-07-16)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: project-dependabot-net481-340
description: Issue #340 Dependabot nuget/packages.config research findings — no verified current framework-drop package, transitive-bump default behavior, directory-glob caveat
metadata:
type: project
---

Issue #340 (docs/features/active/2026-07-16-dependabot-net481-support-340/): researched adding `.github/dependabot.yml` for the `nuget` ecosystem across this repo's 16 top-level `packages.config` project directories (8 prod + 8 test), all pinned to `net481`.

Key findings (2026-07-16):
- Checked NuGet.org Frameworks panels for every distinct package family in the repo's packages.config files (Microsoft.Extensions.*, System.Text.Json, System.Drawing.Common, Apache.Arrow, Microsoft.ML*, Microsoft.Graph, System.Reactive, Svg, FluentAssertions, AngleSharp, FSharp.Core, Microsoft.ApplicationInsights, Microsoft.Data.Analysis, ObjectListView.Official). **None currently has a published version that dropped net462/netstandard2.0/net48x support.** Do not fabricate "known-bad version ceiling" `ignore: versions` ranges without a verified NuGet.org citation — instead use `ignore: update-types: [version-update:semver-major]` scoped to the Microsoft `.NET`-runtime-aligned package families (the only observed pattern where a future framework drop could plausibly land), since major bumps are the only point at which these families have historically changed their TFM list.
- GitHub Docs "About Dependabot security updates" states explicitly: "For other ecosystems [i.e. not npm], Dependabot is unable to update an indirect or transitive dependency if it would also require an update to the parent dependency." This is the citation that satisfies issue #340's "secondary dependency must never be bumped beyond what primary supports" requirement — it is **already Dependabot's default NuGet behavior**, not something the repo's config needs to newly enforce. packages.config has no lockfile, reinforcing this (no transitive entries exist for Dependabot to even discover).
- `directories: ["/*"]` is the concise way to cover all 16 immediate-child project folders in one ecosystem block, but GitHub's docs excerpt available via WebFetch never gave a worked example proving `*` is single-path-segment (not recursive) — flag this as needing a post-merge Insights-tab verification, or fall back to an explicit 16-item directory list.
- GitHub Docs gave two seemingly-conflicting statements on enabling version updates: "commit the file and it's enabled" vs. a Settings→Enable button description. Resolved as: the Settings button is the UI-driven alternative path to *create* the file; committing a hand-authored file via normal PR is the documented enabling mechanism. Recommended a zero-effort post-merge visual check of Settings→Code security and analysis rather than asserting either reading with full certainty (WebFetch's small-model page summarization could not resolve it unambiguously in this session — several per-ecosystem NuGet detail doc URLs 404'd).
- Full findings written to docs/features/active/2026-07-16-dependabot-net481-support-340/research/2026-07-16T16-10-dependabot-net481-support-research.md, including a draft dependabot.yml sketch with groups (analyzers-dev-deps, test-frameworks, microsoft-extensions-and-bcl, graph-identity-telemetry) and the semver-major ignore list.
62 changes: 62 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
version: 2
updates:
- package-ecosystem: "nuget"
directories:
- "/*"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
groups:
analyzers-dev-deps:
patterns:
- "Meziantou.Analyzer"
- "SonarAnalyzer.CSharp"
- "Roslynator.Analyzers"
- "AsyncFixer"
- "Microsoft.CodeAnalysis.BannedApiAnalyzers"
group-by: "dependency-name"
test-frameworks:
patterns:
- "MSTest.*"
- "Moq"
- "FluentAssertions"
- "Castle.Core"
- "Microsoft.Testing.*"
- "Microsoft.TestPlatform.*"
group-by: "dependency-name"
microsoft-extensions-and-bcl:
patterns:
- "Microsoft.Extensions.*"
- "Microsoft.Bcl.*"
- "System.*"
group-by: "dependency-name"
graph-identity-telemetry:
patterns:
- "Microsoft.Graph*"
- "Microsoft.Identity.*"
- "Microsoft.IdentityModel.*"
- "Azure.*"
- "OpenTelemetry*"
- "Microsoft.ApplicationInsights"
group-by: "dependency-name"
ignore:
# Major-version bumps for Microsoft's .NET-runtime-aligned package families are
# the only observed point at which supported TFMs (net462/netstandard2.0) have
# historically changed; gate major bumps behind manual review rather than
# guessing an unverified version-ceiling number (see research §4).
- dependency-name: "Microsoft.Extensions.*"
update-types: ["version-update:semver-major"]
- dependency-name: "Microsoft.Bcl.*"
update-types: ["version-update:semver-major"]
- dependency-name: "System.Text.Json"
update-types: ["version-update:semver-major"]
- dependency-name: "System.Drawing.Common"
update-types: ["version-update:semver-major"]
- dependency-name: "Microsoft.Graph*"
update-types: ["version-update:semver-major"]
- dependency-name: "Apache.Arrow*"
update-types: ["version-update:semver-major"]
- dependency-name: "Microsoft.Data.Analysis"
update-types: ["version-update:semver-major"]
- dependency-name: "Microsoft.ML*"
update-types: ["version-update:semver-major"]
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ An Outlook add-in and set of supporting libraries to **triage, tag, and file ema
* [Build & debug (VSTO add-in)](#build--debug-vsto-add-in)
* [Running the tests](#running-the-tests)
* [Configuration & storage](#configuration--storage)
* [Dependency updates (Dependabot)](#dependency-updates-dependabot)
* [Common issues](#common-issues)
* [Contributing & branches](#contributing--branches)
* [License](#license)
Expand Down Expand Up @@ -153,6 +154,15 @@ Test projects include:

---

## Dependency updates (Dependabot)

* Dependabot's NuGet updater cannot independently bump a transitive/indirect dependency beyond what its referencing primary dependency's own manifest supports. This is documented default ecosystem behavior (GitHub Docs, "About Dependabot security updates"), not a mechanism this repo's `.github/dependabot.yml` invents.
* The `semver-major`-scoped `ignore` rule set in `.github/dependabot.yml` — covering the eight Microsoft `.NET`-runtime-aligned package families (`Microsoft.Extensions.*`, `Microsoft.Bcl.*`, `System.Text.Json`, `System.Drawing.Common`, `Microsoft.Graph*`, `Apache.Arrow*`, `Microsoft.Data.Analysis`, `Microsoft.ML*`) — is this repo's defense against a future `.NET Framework 4.8.1` (`net481`) compatibility drop. It was adopted because no currently-published version of any package referenced in this repo has dropped net481 support (verified 2026-07-16; see `docs/features/active/2026-07-16-dependabot-net481-support-340/research/2026-07-16T16-10-dependabot-net481-support-research.md` §4). Minor and patch updates for the same package families remain unaffected by this ignore rule.
* The config scopes all 16 `packages.config` project directories via `directories: ["/*"]` (a single-segment wildcard matching every immediate-child directory of the repository root). A pre-decided fallback exists if post-merge verification shows under-coverage: the literal 16-entry `directories:` list documented in `docs/features/active/2026-07-16-dependabot-net481-support-340/spec.md` Appendix A, to be substituted for the glob in a follow-up commit only if that verification shows fewer directories scanned than expected.
* **Runbook note (manual, post-merge verification):** after this configuration merges, a maintainer must manually confirm via the repository's **Insights → Dependency graph → Dependabot** tab (or the "Recent update jobs" log) that at least one of the 16 directories is scanned and produces a dependency list. This check is out of scope for any automated toolchain — no format/lint/type-check/test stage applies to a static YAML file — and is tracked as spec AC-11.

---

## Common issues

* **Add-in not loading**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Code Review — dependabot-net481-support (Issue #340)

- Feature folder: `docs/features/active/2026-07-16-dependabot-net481-support-340/`
- Resolved base branch: `main` (merge-base `1ac990b7ef4b5c2a0db388b3bb792be4c4190838`)
- Branch head: `bb669ee938893945d3849ef2a059e93a5c34d102`
- Reviewer timestamp: 2026-07-16T16-40

## Executive Summary

This change is config/documentation-only: it adds `.github/dependabot.yml` (62 lines) and a new `## Dependency updates (Dependabot)` section in `README.md`. There is no C#, PowerShell, TypeScript, or Python source or test file in the branch diff (independently verified via `git diff --name-only` against the merge-base; see the policy audit Section 1 for the full 17-file list). Standard best-practices review therefore focuses on the YAML config's correctness, internal consistency with the spec/AC set, and the documentation's clarity and accuracy, rather than language-specific code-quality rules (naming conventions, null-safety, mocking, etc.), which do not apply to a declarative config file. No blocking findings. Two low-severity observations are recorded below for awareness; neither blocks merge.

## Scope Verified

- Full `git diff --name-only <merge-base>..HEAD` reviewed (17 files, 961 insertions, 0 deletions).
- `.github/dependabot.yml` read and parsed with `python -c "import yaml; ..."` — valid YAML, all 6 expected keys present on the single `nuget` `updates` entry.
- `README.md` diff region (`## Dependency updates (Dependabot)`, lines 157–163) read in full.
- Cross-checked YAML content against `spec.md` AC-1, AC-2, AC-3, AC-6, AC-7, AC-8, AC-9 (schema/ignore/groups/scheduling requirements) — all matched exactly, including the eight `ignore` package families and four `groups` buckets.

## Findings Table

| Severity | File | Location | Finding | Recommendation | Rationale | Evidence |
|---|---|---|---|---|---|---|
| Low | `.github/dependabot.yml` | `ignore` list, lines 42–62 | The `ignore` safety net is scoped by package-family wildcard pattern (e.g., `Microsoft.Extensions.*`) rather than by a resolved list of specific packages actually referenced in the 16 `packages.config` files. This is broader than strictly necessary (it would also gate any future, currently-unreferenced package matching the pattern), though the spec explicitly authorizes this approach (AC-6) as a defense against packages not yet added. | No action required; documented and intentional per spec "Resolved Ambiguities" and AC-6. Consider revisiting if the `ignore` list is observed to gate an unrelated new dependency after future onboarding. | Wildcard `ignore` patterns trade precision for forward-compatibility; the spec makes this trade-off explicitly and narrows blast radius via `update-types: ["version-update:semver-major"]` only (AC-7), so minor/patch/security patches are unaffected. | `spec.md` lines 61–67 ("Constraints & Risks"), `.github/dependabot.yml` lines 42–62 |
| Low | `README.md` | `## Dependency updates (Dependabot)` section, line 161 | The documentation states the config scopes "all 16 `packages.config` project directories via `directories: ["/*"]`" but the AC-4 enumeration evidence (and this reviewer's independent `find` re-run) shows 18 `packages.config` files exist at depth 1 (the 16 named directories plus `VBFunctions`/`VBFunctions.Test`). The `/*` glob covers all 18 in practice, so the behavior is correct, but the prose figure ("16") undercounts the directories actually covered by the glob. | Consider a documentation follow-up clarifying that `VBFunctions`/`VBFunctions.Test` are also swept up by the same glob (as `spec.md`'s own "Directory inventory" section already states), so a future reader of `README.md` alone does not need to cross-reference `spec.md` to learn the true count. | Accuracy of user-facing documentation; the discrepancy is between two of the feature's own artifacts (`README.md` vs. `spec.md`/AC-4 evidence), not a functional defect — the shipped config behaves correctly either way. | `README.md` line 161; `spec.md` line 24 ("Directory inventory"); `evidence/qa-gates/ac4-packages-config-enumeration.2026-07-16T15-56.md` (18 files enumerated) |

No Medium, High, or Blocking findings identified.

## Best-Practices Assessment (non-language-specific)

- **Simplicity**: the YAML structure is flat and readable; no unnecessary indirection.
- **Extensibility**: `groups`/`ignore` entries use wildcard patterns, so future packages matching an existing family pattern are automatically covered without further config edits.
- **Separation of concerns**: the config file and the documentation change are each scoped to a single concern (declarative automation config vs. rationale documentation); no unrelated changes bundled in.
- **Comments**: the `ignore` block in `.github/dependabot.yml` (lines 43–46) includes a `why`-oriented comment explaining the rationale for gating major-version bumps, consistent with the repo's "comment why, not what" guidance.
- **No dependency additions**: the feature introduces no new library/tooling dependency; it only configures an existing GitHub-native service.
- **No temporary files or external services used during verification**: all evidence-capture commands operate against real repository state (`Test-Path`, `Get-ChildItem`, `git status --porcelain`, `python -c "import yaml"`), consistent with the general policy's I/O-boundary and no-temp-file rules for tests (not strictly applicable here since no tests are added, but the same discipline is observed).

## Toolchain Applicability

No format/lint/type-check/test toolchain applies (no source code in any covered language changed). YAML validity was checked via `python -c "import yaml; yaml.safe_load(...)"`, independently re-run by this reviewer with an identical result (`OK`, all 6 keys present). This is the correct and sufficient verification method for a declarative config file with no dedicated repo-level YAML linter configured.

## Conclusion

No blocking or high-severity issues found. The two low-severity documentation/scoping observations above do not block merge and do not represent policy violations — they are noted for optional follow-up polish.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Phase 0 — Instructions Read

- Timestamp: 2026-07-16T15-56
- Issue: #340

## Policy Order

1. `CLAUDE.md` (repo-root standing instructions; policy compliance order)
2. `.claude/rules/general-code-change.md`
3. `.claude/rules/general-unit-test.md`
4. `spec.md`, `user-story.md`, `research/2026-07-16T16-10-dependabot-net481-support-research.md` (this feature folder)

## Files Read

- `CLAUDE.md` — repo-root standing instructions (already resident in session context; reconfirmed applicable policy order).
- `.claude/rules/general-code-change.md` — read in full. This is a config/documentation-only change (no `.cs`, `.csproj`, or test file is touched). Its design-principles sections (simplicity, reusability, separation of concerns) and naming/error-handling sections apply only loosely to a declarative YAML artifact and a documentation section; the file-size limit (500 lines, with an explicit Markdown-documentation exception) and the "avoid breaking public APIs" guidance are the concretely applicable clauses. The seven-stage "Mandatory Toolchain Loop" (format/lint/type-check/architecture/unit/contract/integration) does not apply to this change: there is no C# source, so no formatter/linter/type-checker/test runner has a target to run against. Per `spec.md`'s Definition of Done, this is superseded by the plan's own Phase 7 substitution (YAML-validity check, AC-4 enumeration, AC-10 diff review).
- `.claude/rules/general-unit-test.md` — read in full. No unit-test policy applies to this feature: no test code is added or modified, no production source file is added or modified, and there is no executable behavior to cover with MSTest/Moq/FluentAssertions. Coverage requirements, scenario-completeness requirements, and determinism-infrastructure requirements in this policy have no applicable target in this change.
- `spec.md` (this feature folder, `docs/features/active/2026-07-16-dependabot-net481-support-340/spec.md`) — read in full.
- `user-story.md` (this feature folder, `docs/features/active/2026-07-16-dependabot-net481-support-340/user-story.md`) — read in full.
- `research/2026-07-16T16-10-dependabot-net481-support-research.md` (this feature folder, `docs/features/active/2026-07-16-dependabot-net481-support-340/research/2026-07-16T16-10-dependabot-net481-support-research.md`) — read in full.

## Conclusion

No C# toolchain (CSharpier/analyzer/nullable/`vstest.console.exe`) applies to this change. Phase 7 of the plan substitutes a YAML-validity check plus AC-4/AC-10 verification steps, consistent with `spec.md`'s Definition of Done.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Pre-Change State Baseline

- Timestamp: 2026-07-16T15-56
- Issue: #340

## `.github/dependabot.yml` existence check

- Command: `Test-Path .github/dependabot.yml`
- EXIT_CODE: 0
- Output Summary: `False` (file does not exist)

## README.md baseline

- Command: read `README.md` `## Contents` list and the section ordering around `## Configuration & storage` / `## Common issues`.
- EXIT_CODE: 0
- Output Summary:

Current `## Contents` list (verbatim, lines 11-19 of `README.md`):

```
* [Features](#features)
* [Solution layout](#solution-layout)
* [Getting started](#getting-started)
* [Build & debug (VSTO add-in)](#build--debug-vsto-add-in)
* [Running the tests](#running-the-tests)
* [Configuration & storage](#configuration--storage)
* [Common issues](#common-issues)
* [Contributing & branches](#contributing--branches)
* [License](#license)
```

There is no `Dependency updates (Dependabot)` entry in the `## Contents` list.

Section adjacency confirmed: `## Configuration & storage` (README.md line 142) is immediately followed (after its closing `---` divider at line 154) by `## Common issues` (README.md line 156), with no section in between.
Loading
Loading