Skip to content

fix: 终端工具扫描只认可执行条目 —— 手册页/文档/同名目录不再冒充命令(issue #31) - #32

Merged
KannaKuron merged 1 commit into
KannaKuron:mainfrom
youyv:fix/31-scancommands-executable-extensions
Oct 17, 2026
Merged

KannaKuron merged 1 commit into
KannaKuron:mainfrom
youyv:fix/31-scancommands-executable-extensions

Conversation

@youyv

@youyv youyv commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

按 #31 的评审口径实现,只做扩展名白名单这一步。

已 rebase 到 v0.40.3(536d9e6)之后。唯一冲突在 CHANGELOG.md 顶部:我的条目改号为 ## v0.40.4 — 2026-10-17 并置于 v0.40.3 之上,上游条目一字未动。

改动

  • src/toolchain.js:新增 EXEC_EXTS = {.exe,.cmd,.bat,.com},扩展名不在白名单的条目直接跳过;无扩展名照旧命中(/usr/bin/make、fzf 这类)。纯函数改动、零 io 变更 —— 没有给 io.readdir 加 stat/Dirent,无扩展名目录的区分按你的意见留作后续。
  • tests/smoke.mjs:新增「only executable extensions resolve」一例,锁三层(手册页/文档/目录不命中;无扩展名真可执行仍命中;just.1 排在 just.exe 前时首个可执行命中者路径正确,另覆盖 .EXE 大小写)+ 判定层联动断言(扫不到 ⇒ missing ⇒ isActionable 为真)。
  • CHANGELOG.md:新增 ## v0.40.4 — 2026-10-17 条目(fix)。

验证(rebase 后重跑)

  • npm test(Windows 10.0.26200 / Node 24.19.0):237 pass / 0 fail(基线 236 + 本用例 1;与 v0.40.3 条目记录的 236 tests 对得上,Windows 上无 macOS-only skip)。
  • 新用例在未修复的源码上确实会失败:actual: 'C:/pkg\just.1'、expected: 'C:/pkg\just.exe' —— 正是 issue 里手册页抢先命中的症状;修复后通过。这条用例不是「恒真」的。
  • 真机读数:Casey.Just 便携包目录里 just.1 与 just.exe 并存,字典序 .1 < .e(修复前已实测复现)。

两点说明

  1. 版本号:CHANGELOG 按下一个补丁版写成 v0.40.4,但没有动 package.json / dsh.plugin.json 的 version(现为上游的 0.40.3)—— 发版节奏归你们;若打算并入别的版本号,改个标题即可。
  2. 顺带发现(与本 PR 无关,未改):仓库 package-lock.json 里 5 个依赖的 resolved 指向 registry.npmmirror.com。npm 12 把这类 URL 规格视为 remote 并默认拒绝(EALLOWREMOTE,allow-remote = "none"),所以在这种 npm 上 npm ci 会直接失败。我本地只是把这 5 条临时改回 registry.npmjs.org(integrity 不变)才跑起套件,改动没有进提交(git status 只含上列三个文件)。CI 目前无恙(Node 22/24 自带的 npm 没有这道闸),但值得知道。

目录区分那一步(无扩展名目录 vs 无扩展名可执行文件)等你们定了 io 的形状,我可以接着做。

…on#31)

scanCommands stripped ANY extension, so an entry that merely shared a tool's
stem resolved as that tool. MEASURED: readdir sorts `just.1` (the man page)
before `just.exe` in winget's portable package directory, and the first hit
wins — the card's path column pointed at the man page.

The decision layer followed: classifyToolState() falls back to `hasCommand`
when winget does not own the package, so a machine that genuinely lacks the
command but happens to carry a same-named doc/man page/directory is reported
as `external` and never gets its install entry.

Gate the scan on an executable-extension whitelist (.exe/.cmd/.bat/.com) while
keeping extension-less entries resolving: Git for Windows ships its own
executables that way (/usr/bin/make, fzf).

Directory discrimination is deliberately left for a follow-up — it needs a
stat/Dirent capability on io.readdir and would touch callers, so this stays a
pure-function change with zero io contract drift.

npm test: 237 pass / 0 fail (Windows 10.0.26200, Node 24.19.0). The new smoke
case fails on the unfixed source (actual 'C:/pkg\\just.1', expected
'C:/pkg\\just.exe').
@youyv
youyv force-pushed the fix/31-scancommands-executable-extensions branch from d2902c6 to ba96cd1 Compare October 17, 2026 10:39
@youyv

youyv commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

已 rebase 到 v0.40.3(536d9e6),冲突只在 CHANGELOG.md 顶部:本 PR 条目改号为 ## v0.40.4 — 2026-10-17 并置于 v0.40.3 之上,上游条目未动。rebase 后重跑 npm test:237 pass / 0 fail(Windows 10.0.26200 / Node 24.19.0)。

另外:两个 CI run 目前都是 action_required——首次贡献者的 workflow 需要维护者批准后才会真正执行,不是失败。

@KannaKuron KannaKuron left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

逐项对照了 #31 回复里的验收要点,四点全部达标,本机完整套件已验证,给予通过 ✅

验收对照

  1. 扩展名白名单 + 无扩展名保留:EXEC_EXTS = {.exe,.cmd,.bat,.com},取最后一个扩展名判白名单(与旧剥壳逻辑同位),无扩展名条目照旧命中(/usr/bin/make 一类)——一步到位,没有拆两步。.EXE 大小写用 toLowerCase() 处理并有用例。
  2. ./.. 未加:readdirSync 本就不返回这两项,注释说明了理由,认可省略。
  3. 回归锁三层 + 判定层联动:手册页/文档/目录四类不命中(make.1/tree.txt/jq.md/gdu.d)、无扩展名真可执行仍命中(fzf)、just.1 在 just.exe 之前时首个可执行命中者路径正确——正是 issue 里的真实排序场景;classifyToolState 联动断言(扫不到 ⇒ missing ⇒ isActionable true)也补上了。
  4. CHANGELOG:条目格式规范,带真实案例、验证环境与链接。

本机验证(macOS / Node 24):PR 分支 npm test 236 pass / 0 fail / 1 skip——main 基线 235+1,新增用例恰好多 1,与声明一致(CHANGELOG 里"基线 236"是把 skip 计入了,小误差,合并时维护者顺手修一下即可)。

边界自查(与旧逻辑对照无行为差异):a.b.c、裸 .exe、make.exe.exe 三类条目新旧一致。

第二步(无扩展名目录 vs MSYS 可执行文件,需 io.readdir 提 Dirent 能力)留后续,范围合理。

CI 已代为批准 fork workflow(此前两次都在 action_required 排队),等矩阵绿了就走 squash 合并 + 发 v0.40.4。感谢高质量的报告+修复一体交付!

@KannaKuron
KannaKuron merged commit 6bb7706 into KannaKuron:main Oct 17, 2026
4 checks passed
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.

2 participants