@wirecat/cli-base 0.53.0 → 0.54.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 CHANGED
@@ -8,6 +8,17 @@ Versions before 0.8.0 are in the [git tags](https://github.com/WireCatLabs/cli-b
8
8
  Every entry says what changed as a caller sees it, why, and what to watch for — the rules are
9
9
  [`docs/dev/CONVENTIONS.md`](docs/dev/CONVENTIONS.md#the-changelog).
10
10
 
11
+ ## 0.54.0 — 25.10.2026
12
+
13
+ ### Added
14
+
15
+ - **A Kit surface page in the standards** ([Kit surface](docs/standards/kit-surface.md)) lists the cli-base and cli-core exports that `@wirecat/cli-template` is built on. A change that makes a CLI change its code for one of them ships with a migration note here and with the template already updated, so `npx @wirecat/cli-template upgrade` brings it. Nothing changes in code.
16
+ - **The New CLI page starts with `npx @wirecat/cli-template new`** ([New CLI](docs/standards/new-cli.md)). It gives the command with every flag, the four steps that still need a person, and the same "Done when" checks. A CLI started by hand still passes the same checks.
17
+
18
+ ### Changed — may break callers
19
+
20
+ - **The release lock is one per package, not one per machine** (`WC-REL-3`, [Releases](docs/standards/releases.md)). Two releases of the same package still never run at once on one machine, from any checkout or worktree; releases of different packages now run side by side. The lock is `leemour-release-<package>.lock`, named from `package.json`, so a `package.json` without a name refuses the release. A CLI picks this up by re-running community's `adopt-standards.py --only release-lock`; until then it keeps the old shared lock.
21
+
11
22
  ## 0.53.0 — 25.10.2026
12
23
 
13
24
  ### Added
@@ -120,6 +120,23 @@
120
120
  "!**/fixtures/**"
121
121
  ]
122
122
  },
123
+ {
124
+ "path": "./config/wirecat/no-sqlite-driver.grit",
125
+ "includes": [
126
+ "**",
127
+ "!**/*.test.*",
128
+ "!**/*.spec.*",
129
+ "!**/test/**",
130
+ "!**/tests/**",
131
+ "!**/__tests__/**",
132
+ "!**/fixtures/**",
133
+ "!**/testing/**",
134
+ "!**/scripts/**",
135
+ "!**/bench/**",
136
+ "!**/performance/**",
137
+ "!**/contracts/**"
138
+ ]
139
+ },
123
140
  {
124
141
  "path": "./config/wirecat/no-unbounded-spread.grit",
125
142
  "includes": [
@@ -2,7 +2,7 @@
2
2
  "source": "https://github.com/WireCatLabs/community",
3
3
  "revision": "b22b7ede5931a4058fc763e0a7d6bfe0fbdb87c8",
4
4
  "files": {
5
- "biome.base.json": "5d265b71896cdb0454260fa8d897bd517f61de512f16831e5d5273f29775f9f3",
5
+ "biome.base.json": "63760337a2e68522ad75e0ba163635785a01ec34dbd3cf338a09a4145932cf2a",
6
6
  "cspell.json": "8241122ed4d461976a838099b265ef8f2689a066608257b6fdc250d9b49b58aa",
7
7
  "lefthook.yml": "2f65a2e3103006d43f6d6f0a07ab333c132286157763222a59a5a22676acd391",
8
8
  "markdownlint.json": "5ed7d6980054c539f3f3c0e47a090f1a725b15be2c486a769a836bc6cd48ad2d",
@@ -12,9 +12,10 @@
12
12
  "no-shell-true.grit": "d3943cfa1d7ebbf7be0fa22c2aaf2b7d7aa9ff462f2eb14a7798632764e3875c",
13
13
  "no-unbounded-spread.grit": "f4178e5b74212fef58fec8916b6783d9f4f192ac618aa4ced041c4167bfbf81b",
14
14
  "release-lock-info.mjs": "4abab1f01ceee7d4c709222e923c9a6fc634bcf7b8b64d745a9ac495993310e0",
15
- "release-lock.sh": "f3309e569daea423c35f2a7b51cd55aec24c28160428b67ee2ece05e67fab877",
15
+ "release-lock.sh": "bef364092c4ab595f3b9b4130e23570c8306223228cdfa3e9384230f3b7f4a49",
16
16
  "rumdl.toml": "048b929176f13234324f5825d1e811397f1491b9cb6684a1953e268e2c2ed863",
17
- "check.mjs": "34b266411eaab7707030915f645308e86784b1574b21fa44ca974861a90c9ce1"
17
+ "check.mjs": "34b266411eaab7707030915f645308e86784b1574b21fa44ca974861a90c9ce1",
18
+ "no-sqlite-driver.grit": "19e1f510a88ddd9df44d6db43c1c9b603c3e5bbec03a3f65305b72eac7f09389"
18
19
  },
19
20
  "packageManager": "pnpm@11.20.0",
20
21
  "node": ">=22",
@@ -26,5 +27,11 @@
26
27
  "cspell": "10.3.6",
27
28
  "lefthook": "2.1.16",
28
29
  "markdownlint-cli2": "0.23.3"
30
+ },
31
+ "fileRevisions": {
32
+ "release-lock.sh": "49e630a99d758e3e113749bef2049b258c7262e3",
33
+ "release-lock-info.mjs": "49e630a99d758e3e113749bef2049b258c7262e3",
34
+ "biome.base.json": "06c612c609d870f0ba00010612e0413f65340408",
35
+ "no-sqlite-driver.grit": "06c612c609d870f0ba00010612e0413f65340408"
29
36
  }
30
37
  }
@@ -0,0 +1,15 @@
1
+ language js
2
+
3
+ or {
4
+ `import $_ from $source`,
5
+ `import $source`,
6
+ `export { $_ } from $source`,
7
+ `export * from $source`,
8
+ `export * as $_ from $source`,
9
+ `export type { $_ } from $source`,
10
+ `import($source)`,
11
+ `require($source)`
12
+ } where {
13
+ $source <: r"^[\"'`](?:node:sqlite|bun:sqlite|better-sqlite3|drizzle-orm)(?:/.*)?[\"'`]$",
14
+ register_diagnostic(span=$source, message="The shared store belongs to cli-core (WC-STORE-5): a CLI opens no SQLite driver and writes no SQL against it. Ask cli-core for a store method.", severity="error")
15
+ }
@@ -8,7 +8,16 @@ wirecat_release_lock() {
8
8
  echo "release locking requires flock" >&2
9
9
  return 1
10
10
  }
11
- _wirecat_release_lock="${XDG_RUNTIME_DIR:-/tmp}/leemour-release.lock"
11
+ # Keyed by package name, not folder: one package releases from several checkouts and worktrees.
12
+ _wirecat_release_key=$(node -e '
13
+ const { name } = JSON.parse(require("node:fs").readFileSync("package.json", "utf8"))
14
+ if (typeof name !== "string" || !name) throw Error("package.json has no name")
15
+ process.stdout.write(name.replace(/^@/, "").replace(/[^A-Za-z0-9._-]+/g, "-"))
16
+ ' 2>/dev/null) && [ -n "$_wirecat_release_key" ] || {
17
+ echo "release locking needs a package name in ./package.json" >&2
18
+ return 1
19
+ }
20
+ _wirecat_release_lock="${XDG_RUNTIME_DIR:-/tmp}/leemour-release-$_wirecat_release_key.lock"
12
21
  exec 9>>"$_wirecat_release_lock"
13
22
  if flock -E 75 -w "$_wirecat_release_wait" 9; then
14
23
  printf '%s pid %s since %s\n' "$(basename "$PWD")" "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$_wirecat_release_lock.who"
@@ -9,8 +9,8 @@ It ships in the `@wirecat/cli-base` package. A CLI that depends on cli-base has
9
9
 
10
10
  ## How to use this for a new CLI
11
11
 
12
- Start with the [New CLI](new-cli.md) checklist. Each step names the check that proves it and the area page whose
13
- rules it keeps. A new CLI is ready for its first release when every check under "Done when" passes.
12
+ Start with the [New CLI](new-cli.md) page: `npx @wirecat/cli-template new` makes the repository, and the page lists
13
+ the four steps that need a person. A new CLI is ready for its first release when every check under "Done when" passes.
14
14
 
15
15
  ## Which rule wins
16
16
 
@@ -44,7 +44,8 @@ rules it keeps. A new CLI is ready for its first release when every check under
44
44
  | [CI](ci.md) | `CI` | 12 | Hooks, the pull request budget, full validation, monthly runs |
45
45
  | [Time](time.md) | `TIME` | 6 | UTC in the store and in answers, the zone at input and display edges, date-only filters, tests in another zone |
46
46
  | [Style](style.md) | `STYLE` | 10 | Comments, TypeScript habits, commit messages |
47
- | [New CLI](new-cli.md) | — | — | The checklist for starting a new CLI |
47
+ | [New CLI](new-cli.md) | — | — | Starting a new CLI from the template: the command, the four manual steps, the checks |
48
+ | [Kit surface](kit-surface.md) | — | — | The cli-base and cli-core exports the template is built on, and how a change to one reaches you |
48
49
 
49
50
  Each count leaves out the ids that moved or merged (see "How ids work").
50
51
 
@@ -0,0 +1,50 @@
1
+ # Kit surface
2
+
3
+ ## Scope
4
+
5
+ These are the parts of cli-core and cli-base that the template is built on. A CLI started with
6
+ `npx @wirecat/cli-template new` imports them from its first commit. When one of them changes in a way your code must
7
+ follow, the changelog gives the steps, and the template is already updated, so `npx @wirecat/cli-template upgrade`
8
+ brings the change into your CLI.
9
+
10
+ This page is a reference, not a rule page: it assigns no rule ids. How to start a CLI from the template is on the
11
+ [New CLI](new-cli.md) page. How a release is made is on the [Releases](releases.md) page.
12
+
13
+ ## What the template imports
14
+
15
+ The list is what the template's `src/` imports today, type imports included.
16
+
17
+ | Package and path | Exports |
18
+ |---|---|
19
+ | `@wirecat/cli-base` | `catchCrashes`, `CliError`, `configFilePath`, `mcpErrorResult`, `resolvePaths` |
20
+ | `@wirecat/cli-base/commands` | `annotate`, `CommandInfo`, `describeProgram` |
21
+ | `@wirecat/cli-core/cli` | `AppIdentity`, `changesAuthorityAt`, `commandsCommand`, `configCommand`, `Configuration`, `createProgram`, `environmentOf`, `GlobalFlags`, `itemOf`, `LOCAL_READ`, `outputFor`, `ProgramDefinition`, `ProgramOptions`, `readOnlyLockOf`, `REMOTE_WRITE`, `renderAnswer`, `rootOf`, `run`, `RunOptions`, `settingsFor`, `skillCommand`, `upgradeCommand` |
22
+ | `@wirecat/cli-core/mcp` | `McpCommand`, `registerCommands`, `runCommandForAgent`, `toolsFromCommands` |
23
+ | `@wirecat/cli-core/sends` | `Level` |
24
+ | `@wirecat/cli-core/update` | `appUpdate` |
25
+ | `@wirecat/cli-core/testing` | `ARGV_LOG`, `argvLogSetup` |
26
+
27
+ ## When one of them changes
28
+
29
+ A change that makes a CLI change its code for one of these exports ships with two things:
30
+
31
+ 1. **A migration note in the changelog**, under "Changed — may break callers": what to change in your code, step by
32
+ step. See [Documents](docs.md) for the changelog's shape.
33
+ 2. **A green cli-template job before the pull request merges.** cli-base and cli-core build the template against
34
+ each pull request, so the template is updated in the same change, and `upgrade` has the new version to bring.
35
+
36
+ ## How your CLI stays current
37
+
38
+ - **Exact versions.** The template depends on `@wirecat/cli-base` and `@wirecat/cli-core` at exact versions, the
39
+ normal setup for every WireCat CLI. A CLI made from it starts with the same pins.
40
+ - **Dependabot.** The template's `dependabot.yml` checks `@wirecat/*` every day and opens one pull request for the
41
+ shared packages within a day of a release. Its CI shows whether anything else needs to change.
42
+ - **`upgrade`.** In your CLI, with a clean git working tree:
43
+
44
+ ```sh
45
+ npx @wirecat/cli-template upgrade
46
+ ```
47
+
48
+ For each template file that changed since your version, it asks: apply (merge the change into your file, keeping
49
+ your edits), replace, skip or diff. Without a terminal, `--apply`, `--replace` or `--skip` answers for every file,
50
+ and `--dry-run` lists what each file would get. Then re-run community's `adopt-standards.py` for `config/wirecat/`.
@@ -1,100 +1,81 @@
1
1
  # New CLI
2
2
 
3
- <!-- cspell:ignore rumdl whatsapp -->
4
-
5
3
  ## Scope
6
4
 
7
- The steps to start a new WireCat CLI and the checks that prove each step. Every item names the check that proves
8
- it, or the handbook page whose rules it keeps. A new CLI is done when every check in "Done when" passes.
5
+ How to start a new WireCat CLI: one command that copies the template, the four steps that need a person, and the
6
+ checks that prove the result. A new CLI is done when every check in "Done when" passes.
9
7
 
10
8
  This page is a checklist, not a rule page: it assigns no rule ids. The rules are on the area pages it links. How to
11
- read a rule and which rule wins are in the [index](README.md).
12
-
13
- whatsapp-cli is the worked example: it has every file below. Compare with it when a step is unclear.
14
-
15
- ## Start from the shared standards
16
-
17
- 1. **Create the repository** under `WireCatLabs`, with a `main` branch that takes changes only through pull requests.
18
- Proved by: the repository ruleset. See [Releases](releases.md).
19
- 2. **Install the community presets.** From a reviewed checkout of
20
- [WireCatLabs/community](https://github.com/WireCatLabs/community):
21
-
22
- ```sh
23
- python3 scripts/adopt-standards.py ../whatsapp-cli
24
- ```
25
-
26
- This is the command that was run for whatsapp-cli; use your new repository's folder instead.
27
-
28
- The installer copies the Biome base, the grit plugins, cspell, markdownlint, rumdl, lefthook and the release lock
29
- helper into `config/wirecat/`, pins the tool versions, records the file hashes and writes the `standards.yml`
30
- workflow. Commit the result with the lockfile. Proved by: `pnpm standards:check`, run by `standards.yml`.
31
- 3. **Copy community's `monthly.yml` template** into `.github/workflows/`, and set its cron to a day no other
32
- repository uses. Proved by: the workflow appears in the Actions tab. See [CI](ci.md).
33
- 4. **Add `pr.yml`**, the pull request validation that calls `ci.yml` with platform suites skipped, as shown in
34
- [WC-CI-5](ci.md#wc-ci-5--run-the-full-linux-validation-on-every-pull-request-and-keep-platform-suites-out).
35
- Proved by: the `validation` check on the first pull request.
36
-
37
- ## Toolchain
38
-
39
- 1. **Depend on the shared packages at exact versions.** `@wirecat/cli-base` always, at 0.41.0 or later: it is the
40
- first version that ships this handbook and the `cli-dev` lint and audit that the checks below run.
41
- `@wirecat/cli-core` as well when the CLI is a messenger or uses the shared store, search, MCP server or send guard.
42
- What cli-core already does, the new CLI does not do again. See [Architecture](architecture.md).
43
- 2. **Extend the shared TypeScript configuration**: `@wirecat/cli-base/tsconfig.base.json` for `src/`,
44
- `tsconfig.test.json` for tests and `tsconfig.scripts.json` for `scripts/`. Every directory with `.ts` files is in a
45
- project the build checks. Proved by: `pnpm typecheck`.
46
- 3. **Extend the community Biome base** (`./config/wirecat/biome.base.json`) in the root `biome.json`, and add the
47
- project rules there: the 1,000-line file cap, import cycles and the layer imports. Proved by: `pnpm lint`. See
48
- [Toolchain](toolchain.md) and [Layout](layout.md).
49
- 4. **Add `ci:quick`**: typecheck, build and `cli-dev lint`. Proved by: the pull request CI. See [CI](ci.md).
50
-
51
- ## Commands every CLI has
52
-
53
- 1. **The required root commands.** `cli-dev audit` checks these six paths:
54
- - `commands`: the command tree as JSON, which agents and the audit read.
55
- - `doctor`: checks this machine and the profile, and says what to fix. `doctor --online` logs in once, never
56
- retries, sends nothing and marks nothing read (ruling NEED-288).
57
- - `skill show` and `skill install`: print and install the agent skill from `skills/<cli>/SKILL.md`, which the
58
- package ships. A missing or older skill is suggested on stderr at most once a day (ruling NEED-797).
59
- - `mcp`: the MCP server. Its tools are generated from the commands. See [MCP](mcp.md).
60
- - `upgrade`: updates the CLI.
61
-
62
- Proved by: `cli-dev audit --for <cli>`, rule `required-root`. A CLI on cli-core gets these from cli-core.
63
- 2. **`config`, where the CLI has settings.** cli-core provides it. It is not a required root. See
64
- [Accounts](accounts.md) for the profile, which is always explicit.
65
- 3. **Every command declares its effects and its lifetime**, and has a summary, described arguments and options, and
66
- examples. Proved by: `cli-dev lint`. See [Commands](commands.md), [Output](output.md) and
67
- [Lifecycle](lifecycle.md).
68
- 4. **Every write is gated by a permission.** See [Permissions](permissions.md).
69
- 5. **Add the CLI to the `all` parity group** in cli-base's `PARITY_GROUPS`. That group compares the shared root
70
- commands. Proved by: `cli-dev audit`, rule `same-path-contract`. A messenger also joins cli-core's `parity.json`,
71
- which `pnpm parity:check` reads. See [Testing](testing.md).
72
-
73
- ## Files to add
74
-
75
- 1. **`CLAUDE.md`** (and `AGENTS.md`, if the repository has one): a short file. It links this handbook at
76
- `node_modules/@wirecat/cli-base/docs/standards/README.md`, lists the CLI's "Local rules" below that link, and says
77
- where the private working folder lives. It does not restate handbook rules. See [Documents](docs.md).
78
- 2. **`lint/baseline/`** and `lint/overrides.json`: written once with `cli-dev lint --write-baseline`. The baseline only
79
- shrinks, and at most 10 overrides are allowed. Proved by: `cli-dev lint`.
80
- 3. **The test setup**: `vitest.config.ts` with a `setupFiles` line that points configuration, state, cache and the
81
- store at a temporary directory, and coverage thresholds. Proved by: `pnpm test`. See [Testing](testing.md) and
82
- [Store](store.md).
83
- 4. **`contracts/plan.json`** and its reviewed snapshots for `cli-contract` (cli-testing): help, discovery JSON, MCP
84
- tools and the no-leak check. Proved by: `pnpm contracts:check`. See [Testing](testing.md).
85
- 5. **The test matrix**: `docs/dev/test-matrix.md`, built by `cli-dev test-matrix`. Proved by:
86
- `cli-dev test-matrix --check`.
87
- 6. **The user pages**: `README.md`, `docs/meta.json` and the shared page set, with `docs/commands.md` generated from
88
- the program. Proved by: `cli-dev docs-check --pages` and the CLI's `generate:check`. See [Documents](docs.md).
89
- 7. **`CHANGELOG.md`** with `## Unreleased` at the top and the shared headings, and
90
- **`.github/workflows/changelog-guard.yml`** calling cli-base's `changelog-guard.yml` at a pinned commit. Proved by:
91
- `cli-dev docs-check` and the guard on the first pull request. See [Documents](docs.md).
92
- 8. **`SECURITY.md`**: how to report a vulnerability, linking cli-testing's security method. See
93
- [Security](security.md).
94
- 9. **`bin/release`**, **`release.yml`** and a release skill, copied from the nearest CLI. `bin/release` takes the
95
- release lock (WC-REL-3) and npm's trusted publisher settings name `release.yml`. A messenger CLI also checks a signed
96
- release report (WC-REL-10). See [Releases](releases.md).
97
- 10. **`src/version.ts`** kept in step with `package.json`. Proved by: `pnpm version:check`.
9
+ read a rule and which rule wins are in the [index](README.md). The parts of cli-base and cli-core the template is
10
+ built on are on the [Kit surface](kit-surface.md) page.
11
+
12
+ ## Start with the template
13
+
14
+ ```sh
15
+ npx @wirecat/cli-template new cal-cli --command cal --package @wirecat/cal-cli --owner WireCatLabs \
16
+ --category calendar --content-lang en,ru --sign-in oauth --api official-client --filters time,person,text \
17
+ --never-store tokens,secret-links --untrusted names,links
18
+ ```
19
+
20
+ In a terminal, `new` asks for every answer you leave out. Without a terminal, a missing answer is an error that lists
21
+ the choices. Nothing is guessed.
22
+
23
+ | Flag | What it sets | Choices |
24
+ |---|---|---|
25
+ | `<name>-cli` | the repository folder | any name |
26
+ | `--command` | the command word people type | one word |
27
+ | `--package` | the npm package name | a scoped name, such as `@wirecat/cal-cli` |
28
+ | `--owner` | the GitHub owner of the repository | an owner |
29
+ | `--category` | what the CLI reads | `messenger`, `mail`, `notes`, `files`, `calendar`, `meetings` |
30
+ | `--content-lang` | the languages of the content | a list, such as `en,ru` |
31
+ | `--sign-in` | how the CLI signs in | `oauth`, `token`, `session`, `none` |
32
+ | `--api` | what the service offers | `official-client`, `official-docs`, `unofficial` |
33
+ | `--filters` | how people narrow a list | a list of `time`, `person`, `container`, `text`, `status` |
34
+ | `--never-store` | what the store must never keep | a list of `tokens`, `codes`, `secret-links`, `content` |
35
+ | `--untrusted` | what text comes from other people | a list of `messages`, `files`, `links`, `names`, or `none` |
36
+
37
+ Every choice question also takes `other:<your answer>`.
38
+
39
+ `new` copies the template of its own package version into `<name>-cli/`, renames the command word everywhere, runs
40
+ `git init`, records the template version in `template.json`, writes `docs/dev/DESIGN.md` from your answers and names
41
+ a reference CLI for your category in `AGENTS.md`. It does not install packages, push, create the repository or
42
+ publish. Then:
43
+
44
+ ```sh
45
+ cd cal-cli && pnpm install && pnpm ci:quick
46
+ git add -A && git commit -m "chore: start from @wirecat/cli-template"
47
+ ```
48
+
49
+ Give the agent `docs/dev/DESIGN.md` next. Every example passes a profile explicitly, such as `cal personal doctor`.
50
+ The reference CLI is the one to compare with when a step is unclear.
51
+
52
+ The copy already holds every file this handbook asks for: the required root commands (`commands`, `doctor`,
53
+ `skill show`, `skill install`, `mcp`, `upgrade`) and `config` from cli-core, the MCP server with a tool for every
54
+ command, writes included, the community presets in `config/wirecat/`, the TypeScript, Biome and vitest setup,
55
+ `contracts/`, `lint/`, the test matrix, the user pages, `CHANGELOG.md`, `SECURITY.md`, `bin/release`, and the
56
+ `pr.yml`, `ci.yml`, `main.yml`, `standards.yml`, `changelog-guard.yml`, `monthly.yml` and `release.yml` workflows.
57
+ The rules they keep are on the area pages: [Commands](commands.md), [MCP](mcp.md), [Accounts](accounts.md),
58
+ [Permissions](permissions.md), [Testing](testing.md), [Documents](docs.md), [Releases](releases.md) and [CI](ci.md).
59
+
60
+ Later template changes come in with `npx @wirecat/cli-template upgrade`, file by file: apply, replace, skip or diff.
61
+ See [Kit surface](kit-surface.md#how-your-cli-stays-current).
62
+
63
+ ## Four steps that need a person
64
+
65
+ `new` prints these at the end.
66
+
67
+ 1. **Create the repository** under the owner, with a ruleset on the default branch: no deletion, no force push,
68
+ changes only through a pull request, required status checks, and no bypass. Add the ruleset after the first
69
+ commit is on `main`, since a pull request rule leaves an empty repository no way to get one, and the required
70
+ check names exist only once CI has run. See [Releases](releases.md).
71
+ 2. **Set npm trusted publishing** for the new package, naming `release.yml`, and add any secrets the CI needs. See
72
+ [WC-REL-11](releases.md#wc-rel-11--publish-from-github-actions-with-npm-trusted-publishing).
73
+ 3. **Pick a monthly cron day** no other repository uses. `.github/workflows/monthly.yml` holds a placeholder that CI
74
+ rejects. See [CI](ci.md).
75
+ 4. **WireCat CLIs only: join the shared lists.** A pull request to cli-base's `PARITY_GROUPS` (at least the `all`
76
+ group, which compares the shared root commands), a line in cli-core's `WIRECAT_TOOLS` and a line in cli-docs'
77
+ `tools.json`. A messenger also joins cli-core's `parity.json`. A CLI outside WireCatLabs keeps its parity groups
78
+ in its own repository and runs `cli-dev audit --groups <file>`. See [Testing](testing.md).
98
79
 
99
80
  ## Done when
100
81
 
@@ -32,9 +32,10 @@ on the [CI](ci.md) page.
32
32
  - **Exceptions:** none.
33
33
  - **Applies to:** all CLIs and shared libraries. **Since:** cli-base 0.41.0. **Rulings:** none.
34
34
 
35
- ### WC-REL-3 · `bin/release` takes the machine release lock before it builds or publishes
35
+ ### WC-REL-3 · `bin/release` takes its package's release lock before it builds or publishes
36
36
 
37
- - **Why:** two sessions published at the same time on one machine; one release at a time, across every package.
37
+ - **Why:** two sessions published the same package at the same time on one machine. Different packages do not
38
+ conflict, so each package has its own lock and they release side by side.
38
39
  - **Enforced by:** `<app>: bin/release`.
39
40
  - **Example:**
40
41
 
@@ -44,9 +45,12 @@ on the [CI](ci.md) page.
44
45
  ```
45
46
 
46
47
  The helper comes from the community presets (`adopt-standards.py --only release-lock`). It holds
47
- `${XDG_RUNTIME_DIR:-/tmp}/leemour-release.lock` with `flock` on file descriptor 9 until the release ends.
48
- - **Exceptions:** none. cli-testing still opens the lock with its own `flock` line and moves to the helper.
49
- - **Applies to:** all CLIs and shared libraries. **Since:** cli-base 0.41.0. **Rulings:** NEED-854.
48
+ `${XDG_RUNTIME_DIR:-/tmp}/leemour-release-<key>.lock` with `flock` on file descriptor 9 until the release ends.
49
+ `<key>` is the `name` in `package.json`, made safe for a file name: `@wirecat/cli-core` locks
50
+ `leemour-release-wirecat-cli-core.lock`. The key is the package, not the folder, so every checkout and worktree
51
+ of one package shares the lock. A `package.json` without a name refuses the release.
52
+ - **Exceptions:** none.
53
+ - **Applies to:** all CLIs and shared libraries. **Since:** cli-base 0.41.0. **Rulings:** NEED-854, ASK-336.
50
54
 
51
55
  ### WC-REL-4 · Never break the release lock; wait for the holder and try again
52
56
 
@@ -95,7 +99,8 @@ on the [CI](ci.md) page.
95
99
  - **Enforced by:** review only.
96
100
  - **Example:** tg-cli can release an hour after its last version, and cli-core can ship a breaking change on the same
97
101
  day as the previous one. Bump the library in every CLI that uses it on the day it ships.
98
- - **Exceptions:** none. The release lock (WC-REL-3) still keeps two releases on one machine from running at once.
102
+ - **Exceptions:** none. The release lock (WC-REL-3) still keeps two releases of one package on one machine from
103
+ running at once.
99
104
  - **Applies to:** all CLIs and shared libraries. **Since:** cli-base 0.52.0. **Rulings:** NEED-1741.
100
105
 
101
106
  ### WC-REL-9 · Merged into [WC-REL-8](#wc-rel-8--any-package-may-release-at-any-time)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-base",
3
- "version": "0.53.0",
3
+ "version": "0.54.0",
4
4
  "description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Viacheslav Ptsarev",