plugins/ai-slop/skills/audit/scripts/detect.sh reads its configured arrays through cfg_array, which pipes a jq -r result through tr '\n' ' '. The Windows build of jq terminates its output lines with CRLF rather than LF, so tr converts only the line feed and every element arrives carrying a trailing carriage return.
The effect is that excluded_paths, em_dash_allowed_paths and disabled_rules match nothing on a Windows workstation. A configured exclusion is not reported as failing to apply; it simply never fires, and the detector reports findings on files the repository has deliberately placed out of scope. The tracked .claude/ai-slop.json excludes vendored upstream text, the rule catalog, and the eval fixtures precisely because they carry the tells as data, so on Windows an audit of those paths reports defects that are not defects.
Reproduction
Point the detector at plugins/ai-slop/skills/audit/reference/catalog.md, which the tracked config excludes and which contains twenty em dashes, with rule-em-dash enabled. On a Linux runner the file is declined with cause=excluded-glob. On Windows it is scanned and reported. Dumping the parsed glob array inside cfg_array shows the element as plugins/*/skills/*/vendor/**\r. Interposing a shim on PATH that strips the carriage return from jq's output makes the exclusion apply correctly.
Scope
The carriage return originates in the detector's own jq invocation, not in any caller's configuration file, so a caller cannot work around it by normalizing line endings in the config it supplies. The fix belongs in cfg_array: strip carriage returns alongside the line feeds it already translates.
Why it has not been visible
Continuous integration runs on Linux, where jq emits LF, so every gate and every eval agrees with the configuration. The divergence appears only when a contributor runs the detector locally on Windows, where it is easy to read as the detector disagreeing with the config rather than as a line-ending defect.
Found while reviewing the em-dash regression gate added under #2891, which drives this detector and documents the tracked exclusions as continuing to apply during its runs. That claim holds on the runner and not on a Windows workstation.
Refs #2891
plugins/ai-slop/skills/audit/scripts/detect.shreads its configured arrays throughcfg_array, which pipes ajq -rresult throughtr '\n' ' '. The Windows build of jq terminates its output lines with CRLF rather than LF, sotrconverts only the line feed and every element arrives carrying a trailing carriage return.The effect is that
excluded_paths,em_dash_allowed_pathsanddisabled_rulesmatch nothing on a Windows workstation. A configured exclusion is not reported as failing to apply; it simply never fires, and the detector reports findings on files the repository has deliberately placed out of scope. The tracked.claude/ai-slop.jsonexcludes vendored upstream text, the rule catalog, and the eval fixtures precisely because they carry the tells as data, so on Windows an audit of those paths reports defects that are not defects.Reproduction
Point the detector at
plugins/ai-slop/skills/audit/reference/catalog.md, which the tracked config excludes and which contains twenty em dashes, withrule-em-dashenabled. On a Linux runner the file is declined withcause=excluded-glob. On Windows it is scanned and reported. Dumping the parsed glob array insidecfg_arrayshows the element asplugins/*/skills/*/vendor/**\r. Interposing a shim on PATH that strips the carriage return from jq's output makes the exclusion apply correctly.Scope
The carriage return originates in the detector's own
jqinvocation, not in any caller's configuration file, so a caller cannot work around it by normalizing line endings in the config it supplies. The fix belongs incfg_array: strip carriage returns alongside the line feeds it already translates.Why it has not been visible
Continuous integration runs on Linux, where jq emits LF, so every gate and every eval agrees with the configuration. The divergence appears only when a contributor runs the detector locally on Windows, where it is easy to read as the detector disagreeing with the config rather than as a line-ending defect.
Found while reviewing the em-dash regression gate added under #2891, which drives this detector and documents the tracked exclusions as continuing to apply during its runs. That claim holds on the runner and not on a Windows workstation.
Refs #2891