@kaisers-io/refs 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +134 -0
- package/dist/refs.mjs +43 -43
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,140 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.14.0] - 2026-09-13
|
|
9
|
+
|
|
10
|
+
### Upgrading
|
|
11
|
+
|
|
12
|
+
**A repository declaring a workspace pattern like `packages/**` now reports every member behind
|
|
13
|
+
it.** Those patterns were refused outright, which also stood the unregistered-package pass down for
|
|
14
|
+
the whole ref — so a ref that reported nothing for months may suddenly name hundreds of packages.
|
|
15
|
+
They are not new; they were invisible. `refs doctor` prints the first ten and a count of the rest,
|
|
16
|
+
`refs doctor --json` carries all of them, and
|
|
17
|
+
`refs edit --package=<name> --decline --path=<path> <ref>` records the ones you do not want so they
|
|
18
|
+
stop coming back.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **A workspace pattern that matches at more than one depth is expanded.** `packages/**/*` — the
|
|
23
|
+
most common pnpm spelling — was reported as `unsupported_pattern`, which also made the whole scan
|
|
24
|
+
unreliable and stood the unregistered-package pass down for that ref. A repository declaring it
|
|
25
|
+
got no answer at all, permanently.
|
|
26
|
+
|
|
27
|
+
Such a pattern is now walked from the deepest directory it names outright. Pruning is the
|
|
28
|
+
MATCHER's decision: minimatch answers "could anything below this directory still match?", so a
|
|
29
|
+
subtree no pattern can reach is never entered, a hidden directory is skipped where a wildcard
|
|
30
|
+
would not select it and walked where a pattern names it, and a package boundary does not stop
|
|
31
|
+
the walk — nested packages are ordinary, and both resolvers glob manifest paths rather than
|
|
32
|
+
stopping at one. Selection matches the manifest path for the same reason: `packages/core/**`
|
|
33
|
+
selects `packages/core` itself, because `**` matches zero segments before the manifest.
|
|
34
|
+
`node_modules` and `.git` are never walked under any pattern — a recursive pattern matches an
|
|
35
|
+
installed dependency's path as a string, and reporting those would be reporting a repository's
|
|
36
|
+
dependencies as its own packages.
|
|
37
|
+
|
|
38
|
+
The whole scan runs under one budget shared by every pattern — 32 levels deep, 20 000
|
|
39
|
+
directories, 200 000 entries — because patterns overlap, and a per-pattern budget would charge
|
|
40
|
+
the same tree once per declaration. Reaching a limit is not itself a failure; having to leave a
|
|
41
|
+
subtree that could still match unwalked is, and that is the only condition `scan_budget_exhausted`
|
|
42
|
+
is reported under. A directory the pattern names but the repository does not have stays silent,
|
|
43
|
+
which is ordinary: astro declares `smoke/**/*` and a fresh clone has no `smoke/`.
|
|
44
|
+
|
|
45
|
+
Measured against the resolvers themselves, on fresh clones: `withastro/astro` now detects 554
|
|
46
|
+
packages where pnpm's own workspace listing reports 554 and refs previously reported 37;
|
|
47
|
+
`vercel/next.js` detects 38 where pnpm reports 38; `payloadcms/payload` 53 where pnpm reports 53.
|
|
48
|
+
Pattern semantics were checked against `@npmcli/map-workspaces` over six pattern shapes.
|
|
49
|
+
|
|
50
|
+
- **A ref with hundreds of findings no longer prints all of them.** The same repositories that
|
|
51
|
+
motivated the expansion can legitimately have hundreds of workspace members, so a ref tracking
|
|
52
|
+
three of them would print 551 repair commands into one `doctor` line. Ten are printed, followed
|
|
53
|
+
by a count of what was held back — act on those and run the check again for the next batch.
|
|
54
|
+
`refs doctor --json` carries every finding on the check itself, uncapped: a finding no command
|
|
55
|
+
can repair is never cleared by acting on the ones printed before it, so a capped list would put
|
|
56
|
+
it permanently out of reach.
|
|
57
|
+
|
|
58
|
+
- **A drift finding you have decided against can be recorded, so it stops coming back.**
|
|
59
|
+
`refs doctor` reports every workspace member a checkout declares that the configuration does not
|
|
60
|
+
have. There was no way to say "I looked, and no": the finding returned on every run forever, so
|
|
61
|
+
`config-drift` sat on `warn` permanently and the next real finding arrived in a line already
|
|
62
|
+
being ignored. On a home tracking four monorepos, six of seven findings were decisions that had
|
|
63
|
+
already been made — a repository root, and four packages published nowhere.
|
|
64
|
+
|
|
65
|
+
`refs edit --package=<name> --decline --path=<path> <ref>` records the decision on the ref, as
|
|
66
|
+
the name AND the path. Neither identifies it alone: a name-only record would also silence a
|
|
67
|
+
different package that later takes the name, and a path-only one would silence whatever moves in.
|
|
68
|
+
The `unregistered` finding now prints this command beside the registration command, so both
|
|
69
|
+
answers are available where the question is asked.
|
|
70
|
+
|
|
71
|
+
What a decline does not do: it never touches a finding about a configured entry (`missing`,
|
|
72
|
+
`relocated`, `ambiguous`, `unverifiable`), never suppresses `discovery_incomplete`, and never
|
|
73
|
+
hides the other claimants of an ambiguous name. The package is reported again if it moves.
|
|
74
|
+
`--undecline` withdraws the decision; registering the package clears it in the same write.
|
|
75
|
+
`refs doctor` says how many decisions a run left unreported, so a quiet check is not a silent
|
|
76
|
+
one.
|
|
77
|
+
|
|
78
|
+
## [0.13.1] - 2026-09-12
|
|
79
|
+
|
|
80
|
+
### Upgrading
|
|
81
|
+
|
|
82
|
+
**A repository declaring a workspace pattern like `crates/*/js` will suddenly report packages refs
|
|
83
|
+
could not see before.** The pattern was classified as unsupported, which also made the whole scan
|
|
84
|
+
unreliable and stood the unregistered-package pass down for that ref. `refs doctor` may therefore
|
|
85
|
+
name members on a ref that reported nothing for months. They are not new; they were invisible.
|
|
86
|
+
Register the ones worth routing to, and leave the rest.
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
|
|
90
|
+
- **Every drift finding that has a repair now prints it as a command.** `unregistered` has printed
|
|
91
|
+
a runnable `refs edit --create` since the probe shipped; `missing` and `relocated` described the
|
|
92
|
+
repair in prose and left the reader to construct it. The asymmetry was not deliberate — one of
|
|
93
|
+
the two repairs did not exist as a command at all. `refs doctor` now ends those findings with
|
|
94
|
+
`refs edit --package='<name>' --remove '<ref>'` and
|
|
95
|
+
`refs edit --package='<name>' '<ref>' 'path' '<new>'`, quoted for a shell like every other
|
|
96
|
+
command refs prints. A new path the configuration could not hold is still reported, without a command
|
|
97
|
+
that would only fail validation.
|
|
98
|
+
|
|
99
|
+
Every printed `refs edit` now attaches its option values with `=` and, where a positional would
|
|
100
|
+
otherwise begin with `-`, ends the options with `--`. Quoting gets a value past the shell; refs'
|
|
101
|
+
own parser reads it next, and `refs edit '<ref>' path '-new/pkg'` — a path `zPackagePath` accepts
|
|
102
|
+
— arrived correctly quoted and exited `2` with `unknown option '-new/pkg'`. The terminator is
|
|
103
|
+
printed only where it is needed, so appending `--json` to an ordinary printed line still works.
|
|
104
|
+
|
|
105
|
+
- **`refs edit <ref> --package <name> --remove` unregisters a package.** The counterpart to
|
|
106
|
+
`--create`, and the repair the `missing` finding needed: a package that left a repository's
|
|
107
|
+
workspaces leaves an entry behind that `refs resolve` keeps answering with, pointing at a path no
|
|
108
|
+
checkout has. The only instruction refs could give was to hand-edit `config.toml`. Removal
|
|
109
|
+
touches configuration alone and never consults a checkout — it has to work while the checkout is
|
|
110
|
+
stale, absent, or still carrying the directory. Removing the last entry drops the `packages`
|
|
111
|
+
table rather than leaving an empty one, which `add` and the drift probe read differently.
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- **A workspace pattern whose wildcard is not in its last segment is expanded.** `crates/*/js` —
|
|
116
|
+
the spelling a Rust/JS monorepo uses — was reported as `unsupported_pattern` and every package
|
|
117
|
+
beneath it went undetected. That pattern costs one `readdir` and a literal probe per child, the
|
|
118
|
+
same shape `packages/*` has, so the budget that refused it was measuring the wrong thing. Two
|
|
119
|
+
wildcards still mean two levels and `packages/*/nested/*` is still refused. Measured on a
|
|
120
|
+
repository declaring `crates/*/js` and `turbopack/crates/*/js`: 41 packages detected instead of
|
|
121
|
+
37, with no diagnostics; three other monorepos detect exactly what they did before.
|
|
122
|
+
|
|
123
|
+
- **`tag_format` is detected from every tag, not from the top twenty of a refname sort.** Detection
|
|
124
|
+
counted formats among the first 20 tags of `git tag --sort=-version:refname`. That sort is
|
|
125
|
+
version-aware over the whole refname, so in a monorepo that tags per package it groups by prefix:
|
|
126
|
+
those twenty are one package's tags, not a sample of the repository's. Measured against two real
|
|
127
|
+
repositories, `refs add` proposed `create-astro@{version}` for a repository with 839
|
|
128
|
+
`astro@{version}` tags, and `keystatic@{version}` — a package whose last tag is `0.0.36` and whose
|
|
129
|
+
directory no longer exists — for one where `@keystatic/core@{version}` is the live package with 183 of
|
|
130
|
+
them. Both now resolve correctly, and the two repositories whose detection was already right are
|
|
131
|
+
unchanged.
|
|
132
|
+
|
|
133
|
+
A tag list that could not be read whole now yields no candidate at all rather than one derived
|
|
134
|
+
from whatever survived. `git tag` output is capped at the subprocess stream limit, and the note
|
|
135
|
+
saying so was written to stderr and never read — which did not matter while only twenty lines
|
|
136
|
+
were needed, and does once the count is a claim about all of them.
|
|
137
|
+
|
|
138
|
+
What this establishes is historical plurality, not which package is primary or still alive: a
|
|
139
|
+
retired package with a thousand tags still outvotes its replacement's hundred. The two-phase flow
|
|
140
|
+
shows the candidate for exactly that reason.
|
|
141
|
+
|
|
8
142
|
## [0.13.0] - 2026-09-12
|
|
9
143
|
|
|
10
144
|
### Upgrading
|