Skip to content

Add a diff-scoped comment-hygiene ratchet for build.ps1/test.ps1 and CI - #1061

Merged
jasonleenaylor merged 13 commits into
mainfrom
comment-enforcement
Aug 17, 2026
Merged

Add a diff-scoped comment-hygiene ratchet for build.ps1/test.ps1 and CI#1061
jasonleenaylor merged 13 commits into
mainfrom
comment-enforcement

Conversation

@johnml1135

@johnml1135 johnml1135 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds a mechanical, diff-scoped comment-hygiene gate enforcing the fieldworks-code-commenting standard, wired into build.ps1, test.ps1, and CI. It covers C#/C/C++/IDL, PowerShell, and the <!-- --> comments in project files and Avalonia views. Alongside the banned-content categories it now enforces a per-line width taken from .editorconfig and a content budget that rises in densely branching code. Also fixes a repo-wide bash/PowerShell inconsistency traced back to a misconfigured skill permission that was letting agents default to Bash instead of PowerShell.

The gate blocks coding agents and no one else. Comment length and width are a discipline for generated code, not something a developer should be stopped on:

Who Command Behaviour
Coding agent .\build.ps1 -CommentHygiene Auto-fixes what it can, fails on the rest
Developer .\build.ps1 Gate never runs. Silent.
CI .\build.ps1 Reports and annotates the pull request, exits 0

AGENTS.md and the .github/instructions/* build and test docs now carry the flag on every documented command, including an explicit instruction not to drop it to get a run to pass. powershell-compat.ps1 remains a hard failure for everyone: it catches code that breaks at runtime under Windows PowerShell 5.1, which is a defect rather than a style preference.

265 of the 266 changed .cs files are comment-only -- re-verified at the current tip by stripping comment and blank lines from each file's origin/main and HEAD versions and diffing the remainder: zero non-comment differences. The one exception is a new characterization test. The real review surface is the tooling, CI, and skill files.

Where to look:

  • Build/Agent/comment-hygiene.ps1's added-line filter -- it diffs the merge base against the working tree, not against HEAD, and folds in untracked in-scope files. Both matter: the scan reads each file from disk, so a filter built from committed content goes stale the moment an auto-fix rewrites a file, and git diff never reports a file the author has not staged yet.
  • The same script's -Advisory mode -- reports violations, emits each as a ::warning file=,line= annotation, and exits 0. The first advisory run in a CI job records a marker in GITHUB_ENV so the build and test steps do not annotate the same violation twice.
  • CommentHygiene.psm1's comment-line-too-long check -- it reads max_line_length and tab_width from .editorconfig itself rather than carrying its own number, and measures display columns, not characters, because this repo indents with tabs. It applies to doc comments too: those are exempt from the content budget because of what they say, not because they may run off the screen.
  • Measure-CodeComplexity and the extended budget -- a comment introducing a region that scores 10 or more decision points gets 600 characters instead of 200. Nothing opts in by hand; the threshold was calibrated against the corpus rather than guessed.
  • The same module's XML comment parser -- XML forbids a literal -- anywhere inside a <!-- --> comment, so the standard's usual em-dash-to--- fix is invalid there. A mechanical check catches it and a single - is used instead.
  • .github/workflows/{CommitMessage,check-whitespace,stray-docs}.yml -- switched from shell: bash to shell: pwsh. check_results.log is pre-created before the gitlint pipe because Tee-Object, unlike bash's tee, never creates its target file when the piped command emits zero objects, which is the common case on a clean run.

Deliberately not here: C-style /* */ block comments still are not scanned, in any language. Five now-redundant .sh scripts are deleted rather than kept as a bash fallback. The extended budget keys on measured branching only, so a genuinely non-obvious problem/solution write-up above straight-line code is not detectable and still gets 200 characters. And advisory violations surface on the pull request's Files-changed tab and check-run page, but not on its conversation page; putting them there needs a sticky comment and is left for a follow-up.

Verification: All CI checks pass on the current head, including the full Debug build and test run. That build is the first to compile the 266 changed .cs files and to exercise the four /// doc-comment conversions, which matters because this repo treats compiler warnings as errors. The fixture suite passes under both PowerShell 7 and Windows PowerShell 5.1. The diff-scoped gate is clean, git diff --check is clean, gitlint is clean, and all 19 changed project-file/Avalonia-view files parse as XML. The advisory path was verified against a deliberately bad comment on a throwaway commit, then reverted (see Evidence). Full-repo scan: 22,335 pre-existing violations across 2,836 files, all grandfathered by the ratchet. Not stacked.


Reading this a year from now -- start here

This branch originally shipped with a design spec and implementation plan under Docs/superpowers/. Both are deleted here: the plan was a task-by-task build log now fully superseded by the code, and the design doc's factual claims (PowerShell out of scope, a single non-ascii category flagging any non-ASCII byte, no comment-length redesign) no longer match what shipped. The durable reasoning from both is preserved below instead.

Decisions, and why
  • Blocking for agents, advisory for humans. The goal is that generated comments get fixed inside the agent's own edit/build loop, before review. A post-hoc CI failure would arrive too late and would tax developers for a problem they mostly do not have. The flag is self-declared and permissive by default, which is a real weakness; the alternative considered is under Paths not taken.
  • Ratchet, not zero-tolerance. Modeled on the sibling motif repo's tools/comment-hygiene.ps1, but adapted: new and touched comments must comply, and the existing corpus is not blocked on a repo-wide sweep. A -Full report-only mode exists separately for finding what a file already carries before you touch it.
  • Judgment-based rules stay manual. Accuracy, WHAT-not-HOW framing, and standalone clarity are not mechanically enforceable without high false-positive risk. Only the banned-content categories, ASCII punctuation, length, and width are checked.
  • A content budget and a width limit, doing different jobs. The budget bounds how much a comment says; the width bounds how wide any one line gets. They are independent, and the budget alone exerted no pressure on line width at all: splitting a block across more lines costs nothing against it, so nothing stopped a 205-column line.
  • The width number is read, not chosen. Taking it from .editorconfig means there is exactly one line-length policy in the repo, and it cannot drift.
  • Complexity raises the budget automatically rather than by annotation. An explicit opt-in marker was the alternative; auto-detection was chosen so nothing has to be hand-annotated and the exception cannot be claimed for simple code.
  • Some over-budget comments were promoted to /// rather than shortened. Four sat above a declaration and described that member's own contract, which is what a doc comment is for; // was the original mistake. Doc comments are budget-exempt, so their full text survives. This is not applied to group headers or in-method notes, where it would be a dodge.
  • non-ascii-punctuation, not non-ascii. The category flags a specific Western-typography punctuation set (em dash, arrows, smart quotes), not all non-ASCII content -- this codebase legitimately quotes real script and IPA text in comments.
  • CI never auto-fixes. Auto-fixing and exiting 0 in CI would let a real violation merge behind a green check, since CI has no way to commit the fix back to the branch.
  • Xml's first <!-- --> block is exempt from the length budget. It plays the same file/type-summary role as a C# /// or a PowerShell help block, but Xml has no separate doc-comment syntax to mark it by.
  • Fix root causes with git blame, not guesses. The bash/PowerShell audit started from grepping every "bash" mention in the repo and blaming each one. Nearly all traced to a single commit that set the PowerShell skill's tool permission to route through Bash; that permission, not habit, was the mechanism.
Paths not taken
  • Failing CI when the commits carry AI co-author trailers: harder to evade than a self-declared flag, but it fires after the work is done rather than inside the agent's fix loop, it makes a required check pass or fail depending on authorship, and a human who amends an AI commit inherits the trailer.
  • An explicit marker to license an over-200 comment: rejected in favour of measured complexity, so the exception cannot be attached to code that does not warrant it. The accepted cost is stated under Deliberately not here.
  • Raising the content budget globally instead of keying it to complexity: rejected because the problem is categorical, not a wrong number. Most over-200 comments are ordinary notes that should be shorter.
  • PSScriptAnalyzer alone for PowerShell compatibility: it only catches structural syntax additions via AST analysis under whichever engine runs it. It cannot see that a backtick-escape sequence resolves differently under 5.1 versus 7, since both engines parse it and merely disagree on the value. A dependency-free regex layer for known gotchas was added alongside it.
  • A <!--!-style marker for "this is a doc comment": rejected as inventing syntax the XML/MSBuild/XAML ecosystem does not have. The first-comment-in-document convention was already how every affected file was structured.
  • Keeping the .sh scripts as a bash fallback: rejected once their .ps1 twins were confirmed to have #!/usr/bin/env pwsh shebangs and cross-platform-safe implementations, verified by running check-whitespace.sh and check-whitespace.ps1 side by side and confirming identical output before deleting the original.
Reversals
  • The original design scoped this to .cs only, explicitly excluding PowerShell. PowerShell scanning was added after the tooling's own comments shipped unscanned.
  • An earlier iteration of the comment-length rule was a hard 1-physical-line cap rather than the 200-character budget. The budget is now paired with a separate per-line width limit, which is what that cap was reaching for.
  • The gate originally failed the build for everyone, including CI. It is now blocking only when -CommentHygiene is passed.
  • The powershell skill advised preferring PowerShell Core syntax "where possible". That is backwards for this repo -- CI runs build.ps1 and test.ps1 under Windows PowerShell 5.1 -- and is now a dual-engine requirement pointing at powershell-compat.ps1.
  • Comment edits to WelcomeToFieldWorksDlg.cs, LexOptionsDlg.cs, and FwXWindow.cs are reverted. main had independently ASCII-fixed those same comments while keeping more of their text, and had rewritten the code under LexOptionsDlg.cs, so this branch's comment described logic that no longer exists. All three files now match main exactly.
  • Comment edits in eight further files are dropped. Their comments traced by git blame to unrelated commits spread from 2012 to 2026, rather than to the Avalonia conversion foundation and the four other commits this branch's churn actually belongs to.
  • One commit deliberately adds an over-long comment and the next reverts it. That pair verified the advisory path against a real violation; the tip is byte-identical to the commit before it.
Evidence
  • Comment-only diff claim (265/266 files): for every changed .cs file, stripped comment and blank lines from both the origin/main and HEAD versions and diffed the remainder -- zero non-comment differences across all but one, a genuinely new test file. Re-run at the current tip, not carried over from an earlier state.
  • The added-line filter was scanning the wrong lines: the filter came from the committed diff while the scan reads files from disk, so once a local auto-fix rewrote a file the two were misaligned and the gate reported clean. CI, whose tree matches HEAD, failed on 24 violations at the same commit. Proved by line count: CommentHygiene.psm1 was 430 lines at the commit the local run saw and 748 at the tip, and one reported violation sat at line 706 -- a line that could not exist in a 430-line filter.
  • Untracked files were invisible: a new file carrying a 299-character comment scored exit 0 before the fix and exit 1 after, with nothing else changed.
  • The advisory path, verified against a real violation: a throwaway commit added one 283-column, 280-character comment. The build stayed green, and GitHub's annotations API returned warnings anchored to Src/xWorks/xWorksTests/Search/BulkEditReplaceCharacterizationTests.cs:5 with titles naming both categories. That run also exposed duplicate annotations -- two violations produced four -- because the build and test steps each ran the gate; hence the GITHUB_ENV marker.
  • Complexity threshold calibration: measured against every implementation-comment block already over 200 characters repo-wide. A threshold of 6 would extend 8.3% of them, 8 would extend 4.0%, and 10 extends 2.0% (81 blocks). 10 was chosen as both rare and the conventional McCabe "high complexity" line, and corroborated end to end: the full-repo comment-too-long count drops from 4,020 to 3,943 with the extension enabled.
  • Width was genuinely unenforced: over the full population of comment lines this branch adds, roughly 44% exceeded .editorconfig's 98 columns once tabs are counted as display columns, with a maximum of 205.
  • Churn provenance: git blame over every changed comment line resolved 1,621 of 1,742 (93%) to 31c0a6157, the Avalonia conversion foundation (LT-22625: Add the WinForms to Avalonia conversion foundation #964), then six days old. The eight files whose comments traced elsewhere are the ones dropped above.
  • Most shortening removed duplication, not reasoning: of the 20 blocks the gate flagged after the filter fix, several restated a value or symbol that a neighbouring declaration already owned -- a sentinel's value, a property's own doc comment, three legacy string names documented on the strings themselves, and a coverage note the section divider above it repeated.
  • XML validity: parsed all 19 changed project-file/Avalonia-view files as XML after the re-wrap; 0 invalid.
  • Whitespace: re-wrapping initially copied tab-plus-spaces continuation indents onto new lines, which git diff --check rejects under this repo's indent-with-non-tab setting. Xml comment indentation is normalised to tabs, and the check is clean.
  • PS 5.1 escape bug: a script printing the byte length of a map key built from the backtick-u escape returned 1 (a real em dash) under pwsh and 7 (the literal text) under powershell.exe.
  • Gate performance: Get-Content measured 51ms versus File.ReadAllLines at 1ms on a 5446-line file, and git remote show origin about 515ms versus git rev-parse --abbrev-ref origin/HEAD at about 31ms with no network call. End to end: 5.4s before, about 2.2s after.
  • AI-commit attribution: git blame plus a Co-Authored-By: Claude trailer check on all 1635 violations newly in scope from the C/C++/IDL/Xml extension found 87 across 27 files tracing to AI-authored commits, mostly LT-22625: Add the WinForms to Avalonia conversion foundation #964; all 87 fixed and re-verified clean.
  • StrictMode defects found and fixed: powershell-compat.ps1 read a $Global: variable before assigning it, which errors on every run under Set-StrictMode -Version Latest. Two more of the same shape were introduced and caught while building the width rule.

This change is Reviewable

@johnml1135
johnml1135 force-pushed the comment-enforcement branch from 5d614d3 to 7026fa0 Compare August 13, 2026 11:53
@codecov-commenter

codecov-commenter commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.29630% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.07%. Comparing base (99858db) to head (41ce206).

Files with missing lines Patch % Lines
Src/xWorks/Avalonia/Composer/DetailComposer.cs 81.81% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1061      +/-   ##
==========================================
+ Coverage   38.04%   38.07%   +0.02%     
==========================================
  Files        1499     1499              
  Lines      350127   350145      +18     
  Branches    40239    40239              
==========================================
+ Hits       133215   133306      +91     
+ Misses     187625   187560      -65     
+ Partials    29287    29279       -8     
Files with missing lines Coverage Δ
Lib/src/FormLanguageSwitch/FormLanguageSwitch.cs 0.00% <ø> (ø)
Src/CacheLight/MetaDataCache.cs 93.54% <ø> (ø)
Src/Common/Controls/DetailControls/DataTree.cs 43.76% <ø> (+0.03%) ⬆️
...rc/Common/Controls/DetailControls/ObjSeqHashMap.cs 84.21% <ø> (ø)
Src/Common/Controls/DetailControls/Slice.cs 39.47% <ø> (ø)
Src/Common/Framework/MainWindowDelegate.cs 2.40% <ø> (ø)
Src/Common/FwAvalonia/AvaloniaDialogHost.cs 54.54% <ø> (ø)
Src/Common/FwAvalonia/CompactDialogStyles.cs 100.00% <ø> (ø)
Src/Common/FwAvalonia/Detail/DataTree.cs 95.82% <100.00%> (+0.02%) ⬆️
Src/Common/FwAvalonia/Detail/DetailFocusMemory.cs 71.15% <ø> (ø)
... and 143 more

... and 8 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

NUnit Tests

    1 files  ±0      1 suites  ±0   9m 1s ⏱️ - 1m 23s
5 776 tests +2  5 695 ✅ +2  81 💤 ±0  0 ❌ ±0 
5 785 runs  +2  5 704 ✅ +2  81 💤 ±0  0 ❌ ±0 

Results for commit 41ce206. ± Comparison against base commit 99858db.

♻️ This comment has been updated with latest results.

@github-actions

This comment has been minimized.

johnml1135 and others added 8 commits August 15, 2026 06:24
Enforces the fieldworks-code-commenting standard's banned-content rules
and a non-ascii-punctuation check against lines a diff adds, wired into
build.ps1, test.ps1, and CI. Includes a triage tool that attributes
existing violations to their introducing commit, and a stray-docs CI
gate blocking brainstorming/planning markdown from surviving into a
merged PR.

The comment-length rule is a 200-character budget rather than a hard
1-line cap, since the cap forced every explanation onto one line that
then broke .editorconfig's line-length limit once genuinely non-trivial.
This retroactively surfaced 127 pre-existing over-long comments, all
tracing via git blame to the already-merged Avalonia foundation commit
(#964); all 127 are reformatted into multi-line prose here.

Adds a powershell-compat gate (regex scan plus best-effort
PSScriptAnalyzer) and dual-shell CI test runs, after an independent
review surfaced three functional bugs specific to Windows PowerShell
5.1 vs 7: a Set-StrictMode crash in local base-ref resolution, a CI
checkout missing fetch-depth that left origin/main unresolvable, and a
PowerShell 6+-only escape sequence that silently disabled ASCII
detection under 5.1 -- the exact engine CI's build.ps1/test.ps1 steps
run under. All three are fixed and verified by direct reproduction
under both engines, not just reasoned about.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"ASCII-only" was misleading -- the rule only bans a specific punctuation
set (em-dash, arrows, smart quotes), not all non-ASCII content, which
legitimately appears in comments quoting real script or IPA text.

Also condenses fieldworks-code-commenting/SKILL.md from 203 to 129
lines: cuts the worked-examples section and tightens every other
section's prose. No rule content is removed, only reworded shorter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Widens the diff-scoped gate from C#/PowerShell to also cover C/C++/IDL
(//, ///) and the <!-- --> comments in project files and Avalonia views,
per fieldworks-code-commenting. Adds a first-block doc-comment exemption
for Xml, mirroring /// and PowerShell's help block, since Xml has no
other syntax to mark a file/type-level summary -- without it, sixteen
dialog and project-file overview comments were losing real content to
the 200-character budget.

Fixes two real bugs found while doing this: the gate was scanning every
line of every changed file with Get-Content, ~50x slower than
File.ReadAllLines, plus a network round-trip in local base-ref
resolution via git remote show origin -- both fixed, dropping the gate
from 5.4s to ~2.2s. Separately, the XML spec forbids a literal "--"
anywhere in comment content, so the existing ASCII-punctuation
replacement (em dash to "--") produces invalid XML inside <!-- -->
comments; added a mechanical xml-illegal-double-hyphen check and use a
single "-" there instead.

Blamed the newly in-scope violations to their introducing commits: 87
trace to AI-authored commits and are fixed directly; the remaining
~5000 are pre-existing legacy debt, left for the diff-scoped ratchet to
grandfather like the existing C#/PowerShell backlog.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Audited every "bash" reference in the repo and git-blamed each one.
Nearly all traced to one commit, 5711bf6 ("enable AI workflows"),
which set the powershell skill's allowed-tools to Bash(pwsh:*) instead
of a native PowerShell tool -- the actual mechanism behind agents
defaulting to Bash across worktrees -- plus five .sh scripts
duplicating existing, already cross-platform-safe .ps1 equivalents.

Fixes: the skill now grants PowerShell directly; the five duplicate
.sh scripts are deleted (verified check-whitespace.sh and its .ps1
twin produce identical output first); the three ubuntu-latest CI
workflows (CommitMessage, check-whitespace, stray-docs) now run
shell: pwsh instead of bash, with the sed/GITHUB_ENV-heredoc logic
ported to PowerShell and verified locally; and ~44 bash-labeled doc
code fences for shell-agnostic commands are relabeled powershell.

Left alone: those workflows' ubuntu-latest runner choice, vendored
graphite2/update.sh, the 2018 Bin/list-assembly-references script,
WavConverter.cs's runtime /bin/bash call (real Linux code path, not
tooling), and one git rebase --exec example whose inner string must
stay POSIX syntax regardless of shell, since git always runs --exec
through its own bundled sh.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The build job failed: powershell-compat.ps1 still called
Get-CommentLineClassification with the old -IsPowerShell boolean
parameter, which the comment-hygiene scope-expansion commit replaced
with -Language. Missed because that call site was never exercised
locally this session -- only the module's own fixture suite was run,
not build.ps1 end to end. Fixed and verified directly under both
PowerShell engines.

The commit-message job failed separately: Tee-Object never creates
(or even truncates) its target file when the piped command emits zero
objects, unlike bash's tee, which always creates the file. A clean
gitlint run -- the common case -- produces no output, so
check_results.log never existed for the next step to read. Fixed by
pre-creating the file before the pipeline runs; verified the gap and
the fix directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Narrows the PR's comment edits to the five commits that introduced the
bulk of them: the Avalonia conversion foundation (#964), the Views
render optimizations, the .NET tooling modernization (#678), the Charis
test font change (#945), and the blinking-caret snapshot fix (#943).

The eight files reverted here carried one to five edited comment lines
each, traced by git blame to unrelated commits going back to 2012. Each
file is restored to its merge-base content; all eight diffs were
comment-only, so no code changes are affected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The style section told agents to prefer PowerShell Core syntax, which is
backwards for this repo: CI runs build.ps1 and test.ps1 under Windows
PowerShell 5.1, and powershell-compat.ps1 exists because 6+-only syntax
passes a parse on 7 and then misbehaves there. It now requires both
engines and points at that script.

Adds three traps hit while auditing this branch, each reproduced in
isolation first: an operator after an unparenthesized function call binds
as an argument and is silently ignored; Measure-Object -Sum over an empty
collection returns null and throws on property access under StrictMode;
and returning a collection unrolls it unless prefixed with a comma. Also
notes that --% consumes the rest of the line, so it cannot sit inside a
subexpression.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds a comment-line-too-long rule that reads max_line_length and tab_width
from .editorconfig, so the comment limit is the one the rest of the repo
already follows. It counts display columns rather than characters, since
this repo indents with tabs, and it applies to doc comments too: a doc
comment is exempt from the content budget because of what it says, not
because it may run off the screen. A local run re-wraps the line, CI only
reports it.

The 200-character content budget rises to 600 where the code a comment
introduces scores at least 10 decision points. Measure-CodeComplexity counts
them, stopping at the end of the enclosing block or after 40 lines. Measured
across the whole repo, that extends 2 percent of the comments already over
200, which is the intended rarity.

The gate then re-wrapped this branch's own over-long comments across 210
files. Six needed shortening by hand, and XML comment indentation is
normalized to tabs so the new lines pass git's indent-with-non-tab check.

Also seeds two script-scoped variables before they are read: Set-StrictMode
throws on an unset variable, which powershell-compat.ps1 hit on every run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jasonleenaylor and others added 5 commits August 17, 2026 10:49
comment-hygiene.ps1 built its added-line filter from the committed diff while
the scan reads each file from disk. Once a local auto-fix rewrote a file the
filter pointed at stale line numbers, so the gate checked the wrong lines and
reported clean. CI, whose tree matches HEAD, failed on 24 violations instead.
The filter now diffs the merge base against the working tree.

With that fixed the gate reports 20 over-budget comment blocks. Five wrapped
automatically; the rest are rewritten. Four become /// doc comments, which
keeps their full text: they sit above a declaration and describe its own
contract, and a doc comment is exempt from the content budget.

Most of the shortening drops duplication rather than reasoning. Several
comments restated a value or symbol that a neighbouring declaration already
owned. One test comment explained that no other test covered the case, which
the section divider above it repeated; that divider is deleted too.

Also drops touch vocabulary from the rich-text comment: a keyboard shortcut
stages an edit, it is not a gesture.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment length and width are a discipline for generated code, not something a
developer should be blocked on. build.ps1 and test.ps1 take -CommentHygiene,
which agents are now required to pass: it fails the run on any violation in the
lines the branch adds, so an agent fixes its own comments before review. A
developer build omits the flag and never runs the gate at all.

CI keeps reporting without failing. Under GitHub Actions the gate runs in a new
-Advisory mode that prints every violation, emits it as a ::warning annotation
so it lands on the pull request's diff, and exits 0. powershell-compat stays a
hard failure for everyone, since it catches code that breaks at runtime under
Windows PowerShell 5.1 rather than a style preference.

Also closes a gap in the added-line filter: git diff reports tracked files
only, so a new file an agent had not staged yet went unscanned. Untracked
in-scope files are now folded in with every line treated as added, verified by
probe both ways.

The agent instructions carry the flag on every documented build and test
command, including an explicit note not to drop it to get a run to pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deliberately trips both comment-hygiene categories on a single line so CI has
something real to annotate. To be reverted as soon as the run confirms the
advisory path emits warning annotations without failing the build.

Locally the probe behaves as designed: advisory mode reports two violations,
emits two annotations and exits 0, while enforced mode exits 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The build step runs build.ps1 and the test step runs test.ps1, so the gate ran
twice over the same tree and GitHub registered every violation twice. Verified
on a probe commit: two real violations produced four annotations. The first run
in a job now records a marker in GITHUB_ENV and later steps skip reporting.

Scoped to GitHub Actions on purpose. A marker in the process environment would
persist across runs in one interactive session, so an agent fixing a comment and
re-running would get a false pass on the second run. Local runs always scan.

The marker is appended with UTF8Encoding($false); a BOM part way through the
environment file would break the parse the runner does when the step ends.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jasonleenaylor
jasonleenaylor enabled auto-merge (squash) August 17, 2026 20:31
@jasonleenaylor
jasonleenaylor merged commit 08a02fd into main Aug 17, 2026
8 of 9 checks passed
@jasonleenaylor
jasonleenaylor deleted the comment-enforcement branch August 17, 2026 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants