@oakoss/oakum 0.10.1 → 0.11.1

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 CHANGED
@@ -1,5 +1,57 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.1 (2026-11-15)
4
+
5
+ ### Fixed
6
+
7
+ `check`'s lockfiles look skips a recorded `runtime:` entry that no dependency section declares when the manifest has an `engines.runtime` or `devEngines.runtime`, from which pnpm writes such entries. A root declaring node 24.21.0 under `devEngines.runtime` failed `check --strict` with `` `importers/./devDependencies/node` records `runtime:24.21.0`, which `package.json` does not declare ``, though pnpm's frozen install accepts that lockfile. The skipped entry is counted in the look's line, as an override's is. Every other `runtime:` entry is compared as before. The runtime `engines` or `devEngines` declares is not read, so its entry going stale is not reported.
8
+
9
+ ## 0.11.0 (2026-11-15)
10
+
11
+ ### Added
12
+
13
+ `migrate` from changesets or knope now lists a remaining step to check any commit or CI gate that reads `.changeset/*.md`. oakum writes its own bump files there (an unscoped changesets key such as `"core": patch` becomes `core: patch`), so a gate written for the old tool's files may reject them. oakum does not look for such a gate and says so; the exit code is unchanged.
14
+
15
+ The `@oakoss/oakum` npm package, and every release archive, now ships `schema.json`, the config schema the binary generates. An npm workspace that installs before it lints may point `_config.toml` at it with `#:schema ../node_modules/@oakoss/oakum/schema.json` and delete `.changeset/_schema.json`. `upgrade` then writes no `_schema.json` while the file is absent and the `#:schema` line names any schema other than that file (a URL included), and still regenerates one that exists. The committed `_schema.json` stays the default, because taplo fails to load a `node_modules` schema until the install has run.
16
+
17
+ `oakum status` lists, under "Named like a member, installed from the registry", each pnpm dependency named like a workspace member whose range, or catalog range, the member's version does not satisfy. pnpm installs those from the registry, so oakum cascades nothing along them and rewrites none of their ranges; write `workspace:` where the member is meant. `status --json` carries the same list as `unlinked`. Left out are a declaration pnpm sets aside for another section's, a key a `pnpm-workspace.yaml` override points at the workspace, a peer under `autoInstallPeers: false`, an optional dependency `ignoredOptionalDependencies` names, and a package the config excludes. Pull request comments and job summaries do not show it, since a deliberate registry pin would be reported on every run.
18
+
19
+ ### Changed
20
+
21
+ On the earlier side of a `Cargo.lock` change, coverage now asks `cargo metadata --no-deps` which rows were whose, run read-only on that side's tree in a temporary directory, instead of reconstructing cargo's answer from the manifests. A member outside the workspace root, and a registry named in a member directory's `.cargo/config.toml` when oakum runs from that directory, no longer make a dev-only lock change ask a runtime package for a bump file. Where cargo cannot read the earlier side, as with inheritance its root cannot answer or a registry no config names, coverage is `unverified` (exit 2), quoting cargo, where it used to answer. In a blob-filtered partial clone lacking one of that side's manifests, coverage is `unverified` too, naming a clone without `--filter`; the tree is read without fetching. So is a submodule or a link out of the tree on that side where a member of today's may sit. cargo runs there as the toolchain your checkout resolves to, so a toolchain the earlier side pins is not installed.
22
+
23
+ `release` reads a tag that differs from the version only in build metadata as that version's tag when it looks for tags its resume never reads. With `v0.1.1+b` only on the remote, or on history unreachable from `HEAD`, releasing demo 0.1.1 created a second tag `v0.1.1` and a GitHub release beside it; it now refuses as `unverified`, naming `v0.1.1+b` as a tag for demo 0.1.1. A pending package is looked at too, so any unread tag naming the version it is about to tag refuses.
24
+
25
+ Reading a changelog, oakum now decides which lines a version heading cannot be on the way a renderer does: CommonMark (pulldown-cmark) finds the raw HTML, code blocks and code spans, and an HTML tokenizer reads the raw HTML for comments, tags, quoted attributes and `script`, `style` and `textarea` text. A `</details>` inside an inline comment (`x <!-- </details> -->`), or inside a comment opened earlier in raw HTML, no longer closes a `<details>` block, and one in a code span or a quoted attribute stays text, so a heading the rendered page keeps collapsed no longer vouches for a version. A `<details>` in paragraph text now opens a block as it does on the page, and one left open in a list item, block quote or heading closes with it. A `script`, `style` or `textarea` left open swallows what follows, as it does on the page, and is named as left open. A heading directly under an HTML block with no blank line between is part of that block, as CommonMark renders it, and no longer counts as a heading either.
26
+
27
+ `release` refuses before tagging when the release workflow dist generated for `dispatch-releases = true` is present, recognized by dist's header on its first line, its `workflow_dispatch` trigger and its `gh release create` in this repository (not in the other repository a `github-releases-repo` names), since that workflow creates the tag and GitHub release itself and a tag oakum pushes first collides with it. The refusal names the workflow and says to dispatch it with the tag instead. This includes dist's default output, which also runs on `pull_request`, and a repository where another workflow listens for tags; both tagged before. A workflow whose dist header was edited away is not recognized, nor one from dist before 0.21.1, which wrote no header; regenerate it with a current `dist init`.
28
+
29
+ `check`'s lockfiles look reads the parent's version range in a pnpm `-` override such as `'@x/b@2>@x/a': '-'`. pnpm removes the dependency only under a parent whose version satisfies that range, so with `@x/b` at `1.0.0` the override does nothing; `check` still counted it as covering a dependency the lockfile lacks, and passed a lockfile a frozen install refuses. It now reports that drift. Measured on pnpm 12.16.1: a range, even `*`, needs the parent to have a version that satisfies it, so a parent without a string `version` or a range pnpm cannot parse never matches; a parent named without a range matches any version. A `package.json` whose `name` is not a string, or appears twice, is now read as pnpm reads it (no name, or the last one) rather than refused, and one the look cannot read names the parse error in place of "whose dependency ranges are strings".
30
+
31
+ A Cargo dependency the workspace root's `[patch.crates-io]` or `[patch."<url>"]` points at a workspace member, while the member's version meets the declared range, now counts as that member's dependent, as a path dependency does. cargo builds the member in the registry or git crate's place only while it meets the range, and `version` bumped such a member past it and left the range alone (`helper = "0.1"` beside a `helper` 0.2.0), so cargo silently built the registry's `helper` instead. `version` now retargets the range (`helper = "^0.2.0"`), or leaves a git declaration with no `version` as it is, and bumps the dependent with it; `check` reaches the dependent from a change to the member, so an edit to the member that passed `check --strict` now asks the dependent for a bump file. A workspace whose `[patch]` closes a cycle with a member's dev-dependency now fails discovery, as any dependency cycle does. A patch cargo leaves unused because `Cargo.lock` holds another version it picks instead, which cargo warns about on every build, still counts; a `[patch]` keyed by a registry's name, or in `.cargo/config.toml`, is not recognized.
32
+
33
+ A change inside a Cargo path crate the workspace excludes now reaches the packages that take it through `dependencies` or `build-dependencies`, so `check --strict` asks them for coverage where an edit that left `Cargo.lock` unchanged passed. `check` names the crate (`cli (cargo): changed (via helper)`), and `generate` reads it the same way. A crate taken only as a `dev-dependency` asks nothing.
34
+
35
+ A change to a pnpm catalog entry in `pnpm-workspace.yaml` now reaches the npm members whose `dependencies`, `optionalDependencies` or `peerDependencies` take it with `catalog:`, so `check --strict` asks those members for coverage where it reported no version-managed package changed. `check` names the entry (`changed (via pnpm-workspace.yaml: left-pad)`), and `generate` reads it the same way. The catalog pin `version` writes, an entry installing the same workspace package on both sides with its range retargeted at that package's version, asks nothing, and a `pnpm-workspace.yaml` that does not parse on either side is `unverified`.
36
+
37
+ A `pnpm-lock.yaml` entry added, removed or resolved anew now reaches the npm packages that build it in, those with a `bin` or `resolves-dependencies-at = "build"` whose runtime dependencies lead to it, so `check --strict` asks them for coverage where it reported no version-managed package changed. A library is not asked, since it publishes no lockfile, and `version`'s own lockfile writes ask nothing. `check` names the direct dependency it came through (`changed (via pnpm-lock.yaml: is-odd)`), `generate` reads it the same way, and a lockfile that does not parse on either side is `unverified`. `check`, `add` and `generate` now read `resolves-dependencies-at` as `status` and `version` do.
38
+
39
+ `migrate`'s look for hooks that gate on the old bump-file directory now reads receive-pack's hooks where git runs them. Under a relative `core.hooksPath`, git resolves the path against the git directory for the hooks a push into the repository runs (`pre-receive`, `update`, `proc-receive`, `post-receive`, `post-update`, `push-to-checkout`, and `reference-transaction` during a push), and against the worktree root for every other hook. `migrate` read only the worktree root's, so a `.git/<path>/pre-receive` naming `.bumpy` went unreported and `migrate` exited 0. It now names such a hook, reading from a linked worktree both its own git directory and the main worktree's, each under that worktree's own `core.hooksPath` when `extensions.worktreeConfig` sets one, says `no hook in` each directory when none holds one, and exits 2 (unverified) when one of receive-pack's hooks or its directory cannot be read.
40
+
41
+ A Cargo workspace's root `Cargo.toml` or `Cargo.lock` that is a symlink is now compared where it leads, as cargo reads and writes it. A lock update through `Cargo.lock -> locks/Cargo.lock` changed only the target and passed `check --strict` with no version-managed package changed; it now reaches the packages that ship it, named by the target's path (`locks/Cargo.lock: rusqlite`). Pointing the link, or any link along its chain, at another lock compares the two locks it led to, and each commit is read through its own link. A link that dangles or leads out of the repository is read in place.
42
+
43
+ `check` no longer fetches into a partial clone. Its git reads run with lazy fetching off, so a read that needs an object the clone left out fails, and that look is `unverified` (exit 2), quoting git and naming the partial clone, where it used to fetch the object into `.git` and answer. In a clone filtered past file contents, such as `--filter=tree:0`, `check` refuses before reading anything, naming the remote, its filter, and the two commands that bring the trees in and keep them: `git fetch --refetch --filter=blob:none <remote>`, then `git config remote.<remote>.partialclonefilter blob:none`. A `blob:none`, `blob:limit` or `sparse:oid` clone still lists a branch's changes without fetching, but a branch that edits a `Cargo.toml` or `Cargo.lock` usually needs a blob it lacks, so run `check` in CI from a clone with no filter. In a partial clone, a root file whose blob, tree or commit the clone lacks is `unverified`, where it was read as absent.
44
+
45
+ Coverage counts a file moved from one package to another against both packages; it counted only the one the file moved into.
46
+
47
+ `check --remote` in a partial clone reads the remote's URL past the `[<filter>]` git 2.56 prints after it, where it said it could not establish the remote's transport.
48
+
49
+ ### Fixed
50
+
51
+ `release` no longer refuses to tag when a workflow runs only on `workflow_dispatch` and no workflow listens for tags. Nothing in the repository says such a file, a review bot's or a manual chore's, belongs to the release, yet `release` refused with `downstream .github/workflows/pullfrog.yml … is workflow_dispatch; a tag push will not start it` and left the release untagged. It now tags, and names the file as one a tag push does not start, so a dispatch-only workflow that builds the release can be dispatched with the new tag.
52
+
53
+ `oakum version` no longer writes a dependency range that excludes the version it just released. A pin on a workspace package written as `>0.9.0` was rewritten to `>1.1.0`, and `<2.0.0` to `<1.1.0`, so pnpm or cargo stopped linking the workspace package. A `>` bound now becomes `>=` the new version, and a `<` bound is kept while the new version meets it and becomes `<=` the new version when it does not, in `package.json`, catalogs and `Cargo.toml` alike.
54
+
3
55
  ## 0.10.1 (2026-11-12)
4
56
 
5
57
  ### Fixed
@@ -595,4 +647,4 @@ Release workflow checks out the homebrew tap in a subdirectory so the composite
595
647
 
596
648
  Self-host release CI uploads cargo-dist artifacts into the GitHub Release oakum already created, instead of calling create again.
597
649
 
598
- Generated by oakum 0.10.0.
650
+ Generated by oakum 0.11.0.
package/README.md CHANGED
@@ -18,7 +18,7 @@ Oakum derives which is which — from the binary targets Cargo resolves for a pa
18
18
 
19
19
  ## Design rules
20
20
 
21
- **Config expresses preference; facts are derived.** What depends on what, what is publishable, what needs a bump, and which artifact ships are all read from the repository on every run. Templates, titles, the tag format oakum writes, and commit messages are yours, because they describe output rather than the repository, so they cannot go stale. One key is neither: `resolves-dependencies-at`, set per package under `[packages.<name>]`, which states when your package manager fixes a dependency — a fact about the ecosystem that oakum cannot read from your repository. `init` and `upgrade` will write `_schema.json` next to `_config.toml` and a `#:schema ./_schema.json` line; that directive is taplo's, not part of TOML, so editor support varies. Every key, with its type and any default, is in the [configuration reference](docs/guide/configuration.md).
21
+ **Config expresses preference; facts are derived.** What depends on what, what is publishable, what needs a bump, and which artifact ships are all read from the repository on every run. Templates, titles, the tag format oakum writes, and commit messages are yours, because they describe output rather than the repository, so they cannot go stale. One key is neither: `resolves-dependencies-at`, set per package under `[packages.<name>]`, which states when your package manager fixes a dependency — a fact about the ecosystem that oakum cannot read from your repository. `init` writes a `#:schema ./_schema.json` line, and `init` and `upgrade` keep `_schema.json` next to `_config.toml`, unless `_schema.json` has been deleted and the line names another schema, such as the `schema.json` the npm package ships; that directive is taplo's, not part of TOML, so editor support varies. Every key, with its type and any default, is in the [configuration reference](docs/guide/configuration.md).
22
22
 
23
23
  **Every command writes only the files it owns.** Oakum does not install git hooks, touch git config, edit `AGENTS.md`, write CI workflows, or create commits you did not ask for. `version` owns the manifests it bumps, the lockfile entries those bumps invalidate, and declared `extra-files`. A Cargo version bump invalidates `Cargo.lock`, and a rewritten workspace range invalidates its `pnpm-lock.yaml` entry, so leaving either stale would break the next `--locked` build or frozen install. Nothing beyond that is written. `check` is pure: it reports drift and names the fix, never applies it.
24
24
 
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "MIT",
21
21
  "name": "@oakoss/oakum",
22
- "version": "0.10.1"
22
+ "version": "0.11.1"
23
23
  },
24
24
  "node_modules/detect-libc": {
25
25
  "engines": {
@@ -48,5 +48,5 @@
48
48
  }
49
49
  },
50
50
  "requires": true,
51
- "version": "0.10.1"
51
+ "version": "0.11.1"
52
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "artifactDownloadUrls": [
3
- "https://github.com/oakoss/oakum/releases/download/v0.10.1"
3
+ "https://github.com/oakoss/oakum/releases/download/v0.11.1"
4
4
  ],
5
5
  "author": "Jace Babin",
6
6
  "bin": {
@@ -105,7 +105,7 @@
105
105
  "zipExt": ".tar.xz"
106
106
  }
107
107
  },
108
- "version": "0.10.1",
108
+ "version": "0.11.1",
109
109
  "volta": {
110
110
  "node": "18.14.1",
111
111
  "npm": "9.5.0"
package/schema.json ADDED
@@ -0,0 +1,218 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft-07/schema#",
3
+ "additionalProperties": false,
4
+ "if": {
5
+ "properties": {
6
+ "change-files": {
7
+ "const": false
8
+ },
9
+ "conventional-commits": {
10
+ "const": false
11
+ }
12
+ },
13
+ "required": ["change-files", "conventional-commits"]
14
+ },
15
+ "properties": {
16
+ "change-files": {
17
+ "default": true,
18
+ "description": "When true, the plan reads `.changeset/*.md`.",
19
+ "type": "boolean"
20
+ },
21
+ "commit-message": {
22
+ "description": "Commit message for the version commit. Receives the `oakum status --json` document: `awaiting_tag`, `changed`, `coverage`, `hand_set`, `manages_nothing`, `named_unmanaged`, `packages`, `retired`, `retired_look`, `schema_version`, `selection_empty`, `target`, `uncovered`, `unlinked`, `unmanaged`, `unresolved_scopes`. A string is inline; `{ file = \"path\" }` loads a repository-relative file. Templates render; they do not execute (ADR-0006).",
23
+ "oneOf": [
24
+ {
25
+ "type": "string"
26
+ },
27
+ {
28
+ "additionalProperties": false,
29
+ "properties": {
30
+ "file": {
31
+ "minLength": 1,
32
+ "pattern": ".*\\S.*",
33
+ "type": "string"
34
+ }
35
+ },
36
+ "required": ["file"],
37
+ "type": "object"
38
+ }
39
+ ]
40
+ },
41
+ "conventional-commits": {
42
+ "default": true,
43
+ "description": "When true, commits can feed `generate`, and the plan if change-files is off (ADR-0029).",
44
+ "type": "boolean"
45
+ },
46
+ "exclude": {
47
+ "default": [],
48
+ "description": "Exact package names to leave alone after include filtering (ADR-0027).",
49
+ "items": {
50
+ "minLength": 1,
51
+ "pattern": ".*\\S.*",
52
+ "type": "string"
53
+ },
54
+ "type": "array"
55
+ },
56
+ "include": {
57
+ "default": [],
58
+ "description": "Exact package names to manage. Empty means all packages; then exclude removes (ADR-0027).",
59
+ "items": {
60
+ "minLength": 1,
61
+ "pattern": ".*\\S.*",
62
+ "type": "string"
63
+ },
64
+ "type": "array"
65
+ },
66
+ "packages": {
67
+ "additionalProperties": {
68
+ "additionalProperties": false,
69
+ "properties": {
70
+ "extra-files": {
71
+ "description": "Declared version writes outside the package manifest (ADR-0033).",
72
+ "items": {
73
+ "additionalProperties": false,
74
+ "properties": {
75
+ "format": {
76
+ "description": "Document format. v1 ships json only.",
77
+ "enum": ["json"],
78
+ "type": "string"
79
+ },
80
+ "key": {
81
+ "description": "Dotted key path. `{field=value}` selects a unique array element (ADR-0033).",
82
+ "minLength": 1,
83
+ "type": "string"
84
+ },
85
+ "path": {
86
+ "description": "Leading `/` is repository-root relative; otherwise relative to the package manifest directory.",
87
+ "minLength": 1,
88
+ "type": "string"
89
+ }
90
+ },
91
+ "required": ["path", "format", "key"],
92
+ "type": "object"
93
+ },
94
+ "type": "array"
95
+ },
96
+ "publish-command": {
97
+ "description": "Stored publish command for a post-v0 registry slot. Never executed in v0 (ADR-0011 / ADR-0012).",
98
+ "minLength": 1,
99
+ "pattern": ".*\\S.*",
100
+ "type": "string"
101
+ },
102
+ "resolves-dependencies-at": {
103
+ "description": "Declare that this library bundles dependencies into the published artifact. Binaries are derived; `install` is not configurable (ADR-0009).",
104
+ "enum": ["build"],
105
+ "type": "string"
106
+ },
107
+ "versioning": {
108
+ "description": "How a breaking change file moves a version. `zero-major` (default) maps a major file to a minor bump while the package is below 1.0.0, matching SemVer 2.0 §4. `semver` is how a project releases 1.0.0: the next major file produces 1.0.0, and the key is then inert for that package. Override per package under `[packages.<name>]` so one crate can graduate without taking the rest of the workspace with it.",
109
+ "enum": ["zero-major", "semver"],
110
+ "type": "string"
111
+ }
112
+ },
113
+ "type": "object"
114
+ },
115
+ "description": "Per-package overrides, keyed by the name the manifest declares.",
116
+ "type": "object"
117
+ },
118
+ "pr-status": {
119
+ "default": "both",
120
+ "description": "Pull-request presentation. `none` silences comment and summary; the exit-code gate is not configurable (ADR-0015).",
121
+ "enum": ["comment", "summary", "both", "none"],
122
+ "type": "string"
123
+ },
124
+ "private-packages": {
125
+ "additionalProperties": false,
126
+ "default": {
127
+ "tag": false,
128
+ "version": false
129
+ },
130
+ "description": "Opt-in to version and/or tag packages that are not registry-publishable. Axes are independent (ADR-0027).",
131
+ "properties": {
132
+ "tag": {
133
+ "default": false,
134
+ "description": "When true, unpublishable packages still receive git tags.",
135
+ "type": "boolean"
136
+ },
137
+ "version": {
138
+ "default": false,
139
+ "description": "When true, unpublishable packages still receive version bumps and changelogs.",
140
+ "type": "boolean"
141
+ }
142
+ },
143
+ "type": "object"
144
+ },
145
+ "tag-format": {
146
+ "description": "Tag oakum writes. Receives `package` and `version`. A string is inline; `{ file = \"path\" }` loads a repository-relative file. When unset, oakum writes `v{{ version }}` while one package is tag-managed and `{{ package }}/v{{ version }}` when several are (ADR-0030). Existing tags are derived, not configured (ADR-0004).",
147
+ "oneOf": [
148
+ {
149
+ "type": "string"
150
+ },
151
+ {
152
+ "additionalProperties": false,
153
+ "properties": {
154
+ "file": {
155
+ "minLength": 1,
156
+ "pattern": ".*\\S.*",
157
+ "type": "string"
158
+ }
159
+ },
160
+ "required": ["file"],
161
+ "type": "object"
162
+ }
163
+ ]
164
+ },
165
+ "template": {
166
+ "description": "Changelog template, rendered once per package section. Receives `bump`, `changes`, `date`, `ecosystem`, `notes`, `package`, `repo`, `source`, `target`, `tool_version`, `trigger`, `version`. A string is inline; `{ file = \"path\" }` loads a repository-relative file. Templates render; they do not execute (ADR-0006).",
167
+ "oneOf": [
168
+ {
169
+ "type": "string"
170
+ },
171
+ {
172
+ "additionalProperties": false,
173
+ "properties": {
174
+ "file": {
175
+ "minLength": 1,
176
+ "pattern": ".*\\S.*",
177
+ "type": "string"
178
+ }
179
+ },
180
+ "required": ["file"],
181
+ "type": "object"
182
+ }
183
+ ]
184
+ },
185
+ "title": {
186
+ "description": "Title for the version pull request. Defaults to the version commit's built-in message; a configured `commit-message` does not change it. Where a repository takes its squash subject from the title, that default keeps the subject conventional. Receives the `oakum status --json` document: `awaiting_tag`, `changed`, `coverage`, `hand_set`, `manages_nothing`, `named_unmanaged`, `packages`, `retired`, `retired_look`, `schema_version`, `selection_empty`, `target`, `uncovered`, `unlinked`, `unmanaged`, `unresolved_scopes`. A string is inline; `{ file = \"path\" }` loads a repository-relative file. One template per surface, with conditionals in the body (ADR-0015).",
187
+ "oneOf": [
188
+ {
189
+ "type": "string"
190
+ },
191
+ {
192
+ "additionalProperties": false,
193
+ "properties": {
194
+ "file": {
195
+ "minLength": 1,
196
+ "pattern": ".*\\S.*",
197
+ "type": "string"
198
+ }
199
+ },
200
+ "required": ["file"],
201
+ "type": "object"
202
+ }
203
+ ]
204
+ },
205
+ "tool-version": {
206
+ "description": "Deprecated: oakum no longer reads this key, and `oakum upgrade` removes it. The install pin is the version (ADR-0038)."
207
+ },
208
+ "versioning": {
209
+ "default": "zero-major",
210
+ "description": "How a breaking change file moves a version. `zero-major` (default) maps a major file to a minor bump while the package is below 1.0.0, matching SemVer 2.0 §4. `semver` is how a project releases 1.0.0: the next major file produces 1.0.0, and the key is then inert for that package. Override per package under `[packages.<name>]` so one crate can graduate without taking the rest of the workspace with it.",
211
+ "enum": ["zero-major", "semver"],
212
+ "type": "string"
213
+ }
214
+ },
215
+ "then": false,
216
+ "title": "oakum _config.toml",
217
+ "type": "object"
218
+ }