Skip to content

fix(powershell): bind positional scan paths to -Paths - #316

Merged
PhysShell merged 1 commit into
mainfrom
claude/complex-project-tasks-viyycs
Jul 28, 2026
Merged

PhysShell merged 1 commit into
mainfrom
claude/complex-project-tasks-viyycs

Conversation

@PhysShell

Copy link
Copy Markdown
Owner

Что и зачем

Обёртка сканировала не то дерево, о котором её просили. Документированный вызов из её же .EXAMPLE:

own-check.ps1 -Format msbuild -- src\MyApp

-- завершает разбор параметров в PowerShell, дальше аргументы связываются позиционно, а $Root был объявлен первым — поэтому src\MyApp становился корнем чекаута Own.NET, а сканирование уходило в .. Голая позиционная форма делала то же самое. Корректно связывал только явный -Paths.

Отказ тихий, и это главное. Просишь каталог A — анализируется каталог B, и если в B чисто, пользователь получает зелёный результат без единой ошибки. Это та же ложь, которую арки A1 и A4 выжигали два среза подряд: «не посмотрел» под видом «посмотрел и ничего не нашёл». Здесь, правда, инструмент посмотрел — просто не туда, куда его отправили.

Как починено

Контракт объявлен, а не унаследован из порядка объявления:

[CmdletBinding(PositionalBinding = $false)]
param(
    ...
    [Parameter(Position = 0, ValueFromRemainingArguments = $true)]
    [string[]]$Paths
)
Root   → только именованный -Root
Paths  → явный -Paths или позиция 0

Перестановка параметров дала бы тот же результат сегодня и оставила бы смысл висеть на той же неявной механике, которая уже дважды устроила представление.

Проверено на настоящем скрипте (пробник собран из его же блока параметров, обрезанного перед первой стадией):

Вызов Было Стало
-Format github -- /t/a Root=/t/a Paths=[/t/a]
-Format github /t/a Root=/t/a Paths=[/t/a]
-Format github -Paths /t/a Paths=[/t/a] без изменений
-Root /checkout -Format github -Paths /t/a корректно без изменений
-Format github Paths=[.] без изменений
-Format github -- /t/a /t/b Root=/t/a Paths=[/t/a|/t/b]

Граница: pwsh -File

При запуске через pwsh -File script.ps1 ... -- <path> литерал -- перехватывается хостом ещё до связывания параметров и отвергается как неоднозначное имя. Это поведение PowerShell для -File, а не дефект скрипта и не повод раздувать срез. Поддерживаемые формы для такого запуска:

pwsh -File own-check.ps1 -Format github <target>
pwsh -File own-check.ps1 -Format github -Paths <target>

В интерактивной сессии и при & own-check.ps1 работают все три формы, включая --.

Строка, отбрасывающая литерал -- из $Paths, сохранена: в сессии PowerShell съедает токен сам, но при сплаттинге (& own-check.ps1 @args) он реально доходит как значение. Комментарий приведён в соответствие.

Что добавлено в CI

Сквозной тест именно тихой подмены цели, а не наличия какой-то находки: стоя в чистом рабочем каталоге, просим цель с гарантированным OWN001 и требуем, чтобы находка вернулась, а файл из cwd не появился в выводе вовсе. Плюс:

  • формы -- <target> и -Paths <target> обязаны дать идентичный вывод — эквивалентность публичных форм, а не «обе что-то сказали»;
  • два позиционных пути обязаны дойти оба ([string[]] заявлен как тип, доказательство на одной строке его не устанавливает);
  • без цели по-прежнему сканируется ..

Заодно исправлен устаревший комментарий над джобой: обёртка исполняется на Linux достаточно далеко, чтобы доказать ярус отказа первой стадии, — Windows требуется её успешному extraction path.

Тип изменения

  • feat — новая возможность
  • fix — исправление бага
  • docs — документация
  • refactor / chore / test / ci — без изменения поведения

Как проверено

  • Локально с PowerShell 7.4.6 против настоящего скрипта — вся матрица связывания выше, включая множественные пути и дефолт .

  • Ярус отказа первой стадии после правки держится в обеих формах: LASTEXITCODE = 2

  • Фикстуры проверены на верность вердиктов до пуша: целевой файл действительно даёт OWN001, файл рабочего каталога действительно чист

  • Тело каждого шага проверено парсером PowerShell

  • CI ветки зелёный на bfcab5e — 19 джоб, ни одной не-успешной; Windows-джоба прошла всеми шестью шагами с первой попытки:

    OK: every documented form scans the requested target; the two public forms agree
    OK: stage-1 failure landed in the hard-error tier (2)
    OK: clean tree exits 0
    OK: findings -> 1 with the flag, 0 without, identical output
    
  • python tests/run_tests.py / ruff — не применимо: Python и продуктовый код не менялись

Связанные issue

Closes #315. Refs #313, #314 (где дефект был найден исполнением обёртки).

Чеклист

  • изменение покрыто тестом/селфтестом (или объяснено, почему нет)
  • README/docs обновлены при необходимости — комментарий над джобой приведён в соответствие с фактами
  • коммиты в conventional-commit стиле (feat:, fix:, docs: …)

Generated by Claude Code

Loading
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.

PowerShell wrapper: documented positional paths bind to -Root and silently scan "."

2 participants