Path.glob raises NotImplementedError for a non-relative pattern, which a string `workspaces` (iterated char by char, so "/") or an absolute entry produces. The (OSError, ValueError, TypeError) catch missed it, so the error escaped to the caller's suppress(Exception) and no lock was reverted at all -- back to autostash every run. Non-list values are now ignored and each pattern is tried on its own so a bad one just owns nothing.
install.sh: read the workspace globs with `while read` instead of an unquoted $(...) so they are never pathname-expanded against the caller's CWD before `case` sees the pattern.
Keep the two discriminating cases from #112396: a dirty workspace manifest preserves the
root lockfile, and a manifest outside the workspace graph does not. The non-workspace case
in the original PR created an untracked file that `git diff --name-only` never lists, so it
passed on unfixed main; the fixture now commits vendor/foo/package.json first. The git
helper pins an author identity so the test runs on CI runners without git config.
Restore the WHY in `_discard_lockfile_churn`'s docstring (the autostash-every-run motive)
and document that `_npm_lockfile_owners` mirrors `update_cmd_deps._npm_manifest_paths`.
Co-authored-by: KoNit-K <124019182+KoNit-K@users.noreply.github.com>
A workspace manifest can change the dependency graph represented by the root lockfile. Discover the root package workspaces and preserve the root lock when a covered manifest is dirty, while retaining same-directory nested ownership and discarding unrelated churn. Fixes#112378.
For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.