hermes-agent/scripts
jinglun010 051217342b feat(linter): detect subprocess text=True without explicit encoding=
Adds a new rule to scripts/check-windows-footguns.py that flags
subprocess.run/Popen/call/check_output/check_call(..., text=True, ...) calls
missing an explicit encoding= kwarg.

On Chinese Windows (cp936/GBK) and other non-UTF-8 default codepages,
text=True without encoding= decodes child output with
locale.getpreferredencoding(False), crashing _readerthread with
UnicodeDecodeError on non-default-codepage bytes (issues #47939, #53428,
rule prevents future regressions.

Rule design:
- Pattern matches 'text=True' / 'text = True'
- post_filter skips lines that:
  - already pass encoding= on the same line
  - are method definitions (def text)
  - contain text=True inside string literals
  - are not subprocess-shaped calls (heuristic via _is_likely_subprocess_call)
- Two helper functions: _is_likely_subprocess_call, _looks_like_string_literal
- Multi-line calls where subprocess.X( and text=True are on different lines
  are not flagged (acceptable false negative for a line-based scanner)

Also fixes the linter's own footgun: get_staged_files() and get_diff_files()
used subprocess.check_output(text=True) without encoding= — now fixed.

Suppresses 4 false positives on non-Windows platform-exclusive calls:
- tools/voice_mode.py (Termux/Android)
- tools/environments/singularity.py (Linux HPC)
- plugins/google_meet/cli.py (macOS system_profiler)

Test plan:
- 21 unit tests in tests/scripts/test_footgun_subprocess_encoding.py
- TestDetection: 6 cases verifying the rule flags real subprocess calls
- TestSuppression: 7 cases verifying false-positive avoidance
- TestHelpers: 7 cases for the two helper functions
- TestFullRepoScan: scans the whole tree and asserts the new rule finds
  only the 7 call sites that PR #60741 fixes (or zero, once #60741 merges)

Verified: full-repo scan reports 7 matches on main (the #60741 sites),
4 platform-exclusive calls correctly suppressed, zero false positives.
2026-07-24 11:45:57 -07:00
..
ci fix(ci): report E2E evidence upload failures (#69901) 2026-07-23 05:45:17 +00:00
lib fix(hermes): heal broken managed Node tree instead of PATH fallback 2026-06-26 20:10:20 +05:30
tests fix(install): detect Git Bash Mandatory ASLR failures (#64651) 2026-07-16 22:46:46 -04:00
whatsapp-bridge fix(whatsapp): unpin Baileys from git commit, use published 7.0.0-rc13 (#60643) 2026-07-07 19:49:26 -07:00
add_contributor.py fix(ci): make tests, workflows, and attribution reliable under load (#66373) 2026-07-17 20:55:24 +00:00
analyze_livetest.py fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336) 2026-07-05 13:42:46 -07:00
benchmark_browser_eval.py perf(browser): route browser_console eval through supervisor's persistent CDP WS (180x faster) (#23226) 2026-05-10 07:37:55 -07:00
build_model_catalog.py feat(models): catalog-labeled silent default — GLM-5.2 marked "default": true in the model catalog 2026-07-15 00:10:31 -07:00
build_skills_index.py fix(skills): let ClawHub index build walk past the 12s browse budget (#44500) 2026-06-11 18:03:11 -04:00
capture-cage-terminal.sh feat(devshell): add terminal UI capture tools (#69629) 2026-07-22 17:28:21 -04:00
check-windows-footguns.py feat(linter): detect subprocess text=True without explicit encoding= 2026-07-24 11:45:57 -07:00
check_subprocess_stdin.py fix: Windows guard, dedup recovery, profile-safe paths, clear SO_RCVTIMEO 2026-07-20 12:48:50 +05:30
contributor_audit.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
dev-sandbox.sh feat(dev-sandbox): add --from DIR to seed sandbox HERMES_HOME (#66486) 2026-07-17 19:45:41 +00:00
discord-voice-doctor.py codebase: add encoding='utf-8' to all bare open() calls (PLW1514) 2026-05-08 14:27:40 -07:00
docker_config_migrate.py fix(docker): restore config backups after failed boot migration 2026-06-24 15:23:23 +10:00
docker_rebootstrap_nous_session.py fix(auth): apply newer hosted bootstrap session (#64612) 2026-07-16 08:52:47 +10:00
hermes-gateway fix: prevent systemd restart storm on gateway connection failure 2026-03-21 09:26:39 -07:00
install.cmd fix(docs): update all install instructions everywhere 2026-06-04 21:07:45 -04:00
install.ps1 fix(desktop): stop hard-failing pack on non-git checkouts + fix ZIP-path autocrlf (supersedes #67643) (#67730) 2026-07-19 19:29:36 -04:00
install.sh rip out brew + pip/PyPI wheel support (#68217) 2026-07-22 16:51:01 -04:00
install_psutil_android.py revert(windows): roll back terminal-popup PRs #53791 #53810 #53829 (#53853) 2026-06-27 15:59:00 -07:00
iso-certify.py feat(dashboard): isolate turns in compute host (#65895) 2026-07-16 15:24:03 -04:00
keystroke_diagnostic.py docs: add Windows-Specific Quirks section to hermes-agent skill + keystroke diagnostic 2026-05-08 14:27:40 -07:00
kill_modal.sh refactor: replace swe-rex with native Modal SDK for Modal backend (#3538) 2026-03-28 11:21:44 -07:00
lint_diff.py feat(ci): add typecheck (warnings only in CI) 2026-05-06 10:58:12 -04:00
LIVETEST_README.md test(tool-search): add live A/B harness, drop checked-in transcripts 2026-05-29 02:04:12 -07:00
profile-tui.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
release.py chore: fix contributor attribution for desktop PR 2026-07-24 12:54:29 -05:00
run_tests.sh fix(nix): dirty-tree wrapper bug + filtered rebuild scope + overlay alias (#65237) 2026-07-15 21:45:35 -04:00
run_tests_parallel.py fix(ci): make tests, workflows, and attribution reliable under load (#66373) 2026-07-17 20:55:24 +00:00
sample_and_compress.py fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336) 2026-07-05 13:42:46 -07:00
tool_search_livetest.py test(tool-search): redact secrets from harness transcripts + console 2026-05-29 02:04:12 -07:00