You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 405a78e
Browse filesBrowse the repository at this point in the historyBrowse files
fix(cli): os deploy takes --confirm-global-uniques on a self-hosted runtime (#31369)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XK6xDkLoiBC4HTcoqUryg5E)_Fixes#31338
Clause-②: yes — `os deploy` gains an accepted flag
(`--confirm-global-uniques`), widening a published CLI command's accept
set; the seat's own review of the declaration is owed before landing
Metadata-protocol: none
## 维护者速读
- 改了什么:`os deploy` 新增 `--confirm-global-uniques` 开关,在自托管运行时(`os
environments
use-runtime`)路径上和已有的两个升级确认(`--confirm-access-upgrade`、`--confirm-upgrade`)走同一处转交给内嵌的
`os package install`;目标是 ObjectOS Cloud 时照两个升级确认的做法,在构建和发送前拒绝。文档
`cli.mdx` 补了这一行。
- 为什么改:自托管部署遇到全局唯一约束停止(`UNIQUE_SCOPE_CONFIRMATION_REQUIRED`)时,CLI
打印的重试命令是 `os deploy --confirm-global-uniques`,但 `os deploy`
不认这个参数,照抄(尤其是 agent 照抄)会被当未知参数拒绝,部署路径也无法传这个确认。
- 风险与回滚:只加一个可选开关,不传时请求体与以前逐字节相同;`os package install`
和两个升级确认不变;`@objectstack/cli` patch;回滚即 revert。
- 先看:`packages/cli/src/commands/deploy.ts` 的 `CONFIRMATION_FLAGS` /
`confirmationArgv`(唯一转交处)和 Cloud 拒绝循环;`packages/cli/test/deploy.test.ts`
新增三条用例。
- 两分钟验证:`pnpm --filter @objectstack/cli exec vitest run --project unit
test/deploy.test.ts`,预期 34/34 通过;其中「declares every confirmation flag the
embedded install prints」一条在 `os package install` 将来新增确认开关而 `os deploy`
没跟上时会变红。
- 需要你做的:无,席位落地。
## What changes
On a self-hosted runtime target, `os deploy` runs `os package install`
in-process with `retryCommand = 'os deploy'`, so every stop that install
prints names `os deploy` as the retry. The installation-wide uniques
stop (`UNIQUE_SCOPE_CONFIRMATION_REQUIRED`, ADR-0120 D5e) printed `os
deploy --confirm-global-uniques`, a flag `os deploy` did not declare:
oclif refused it as an unknown flag (exit 2), and the deploy path had no
way to pass the confirmation.
- **`packages/cli/src/commands/deploy.ts`.** Declares
`--confirm-global-uniques` (a boolean, help text naming `os package
install --confirm-global-uniques`, as the two upgrade confirmations name
theirs). The three confirmations are now one list, `CONFIRMATION_FLAGS`,
and one function, `confirmationArgv`, turns the given ones into install
argv. `deployToRuntime` takes that argv instead of two token parameters,
so there is one forwarding seam and no second copy of the install
command's handling. As before, the confirmations go to the install only;
the dry run sends none (install-local answers `dryRun` before its
uniques gate, `marketplace-install-local-plugin.ts`
`answerUpgradeDryRun` precedes the `GLOBAL_UNIQUE_CONFIRMATION_REQUIRED`
stop).
- **ObjectOS Cloud target.** The flag means nothing there, so it is
refused before anything is built or sent, exactly as
`--confirm-access-upgrade` and `--confirm-upgrade` already are (same
loop, same sentence, exit 1).
- **`content/docs/deployment/cli.mdx`.** The `os deploy` flag table
gains the `--confirm-global-uniques` row; § To a self-hosted runtime
step 3 names the three confirmations passed through, the uniques stop,
and that the printed retry names `os deploy`.
- **Changeset** `.changeset/31338-deploy-confirm-global-uniques.md`:
`@objectstack/cli` patch.
`install.ts` is untouched: the seam did not need sharing.
## Tests
`packages/cli/test/deploy.test.ts`, in the use-runtime block, three new
cases:
1. The uniques stop's retry names `os deploy --confirm-global-uniques`,
and `os deploy --confirm-global-uniques` reaches the install with
`confirmGlobalUniques: true` (and the dry run without it).
2. Every `confirm-*` flag `os package install` declares is declared by
`os deploy` (the class guard: a future install confirmation that `os
deploy` does not take reds here).
3. `--confirm-global-uniques` is refused on an ObjectOS Cloud target
before anything is built or sent.
CONTROL: the existing access-upgrade and schema-upgrade cases and their
Cloud refusals pass unchanged; `test/package-install-dry-run.test.ts`
passes unchanged.
<details><summary>Red on main (cases added, source at origin/main
e735425)</summary>
```text
× the installation-wide uniques stop's retry names os deploy --confirm-global-uniques, and the confirmation passes through
× declares every confirmation flag the embedded install prints as its retry
× --confirm-global-uniques is refused when the target is ObjectOS Cloud, before anything is sent
…or edit the app's metadata to `unique: 'organization'` and rebuild.: expected 2 to be undefined
AssertionError: confirm-global-uniques: expected [ 'env', 'wait', 'wait-timeout', …(4) ] to include 'confirm-global-uniques'
AssertionError: expected 2 to be 1 // Object.is equality
Tests 3 failed | 31 passed (34)
```
Exit 2 is oclif's unknown-flag refusal: the printed retry was refused.
</details>
<details><summary>Ablations (scripts/ablation-replace.mjs, restore
proven blob == HEAD 2b59a9c and git diff HEAD empty)</summary>
The test imports `../src/commands/deploy.js` directly, so no dist leg
applies.
A. Cloud refusal skips the new flag (`|| flag ===
'confirm-global-uniques'` in the refusal loop's `continue`):
```text
× --confirm-global-uniques is refused when the target is ObjectOS Cloud, before anything is sent
AssertionError: expected [ { …(4) } ] to have a length of +0 but got 1
Tests 1 failed | 33 passed (34)
```
B. The forwarding drops the new flag (`|| flag ===
'confirm-global-uniques'` in `confirmationArgv`'s empty return):
```text
× the installation-wide uniques stop's retry names os deploy --confirm-global-uniques, and the confirmation passes through
AssertionError: expected undefined to be true // Object.is equality
Tests 1 failed | 33 passed (34)
```
</details>
## Acceptance notes
- **Clause-②: yes (widening).** `os deploy`'s accept set grows by one
flag; nothing it accepted before is refused, and with the flag absent
the install body is byte-identical to before.
- **PR #31335 and `cli.mdx`.** #31335 (skills lane, open) edits
`cli.mdx` § `os dev` (around L169-L174) only; this PR edits § `os
deploy`'s flag table and § To a self-hosted runtime step 3 (around
L3245, L3267). No overlapping hunk, so the doc line stays in this PR;
whichever lands second merges cleanly.
- **Not edited here.** The platform skill's use-runtime exit-1 paragraph
(`skills/objectstack-platform/references/operations.md`, added by
#31335) is the skills lane's; the line it needs is in the report's
`out_of_scope_findings`. The `os deploy` flag table still has no
`--confirm-upgrade` row (#31335's "Other sites found" already names it);
left alone.
## Verification
All local readings are on head `7e77a2ba` (the merge of `origin/main`
`d0512c2f` into fix commit `cecb4075`; the merge brought no
`packages/cli` change).
- **Derived gates.** `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` derived 96 commands against merge
base `e73542555` (4 paths, +83/-18). All 96 ran after a full `turbo run
build --filter='./packages/**'` (81/81 tasks): **96 × exit 0**. `--ran`
reconciliation: "96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN", exit 0.
Per-command record: project file `pm-orders/server/31338-gates-ran.txt`.
- **cli unit tier.** `pnpm --filter @objectstack/cli exec vitest run
--project unit --maxWorkers=2` under the verify lock: `VERDICT
command-exit 0`, Test Files 401 passed (401), Tests 5671 passed (5671).
Started on `cecb4075`; `packages/cli` is byte-identical on `7e77a2ba`.
The integration tier is declared to CI (the diff touches no integration
test, `bin/` or spawn helper).
- **cli typecheck.** `NODE_OPTIONS=--max-old-space-size=6144 pnpm
--filter @objectstack/cli typecheck` (`tsc --noEmit &&
check:test-typecheck`): `VERDICT command-exit 0`, test layer OK.
- **eslint** on `packages/cli/src/commands/deploy.ts` and
`packages/cli/test/deploy.test.ts`: exit 0.
- **Commit trailers.** `node scripts/check-commit-card-trailers.mjs
--range origin/main..HEAD`: exit 0.
- Repo-wide `pnpm lint`, `test:repo` and the other CI-owned families: CI
on this PR.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01FEkQ5o7rUkfGZf2hPcQqZJ
Co-authored-by: Claude <noreply@anthropic.com>
fix(cli): `os deploy` to a self-hosted runtime takes `--confirm-global-uniques`, the retry its installation-wide uniques stop prints
6
+
7
+
Clause-②: yes (widening) — `os deploy` gains an accepted flag, `--confirm-global-uniques`, widening a published CLI command's accept set
8
+
Metadata-protocol: none
9
+
10
+
-**What was wrong.** With a self-hosted runtime as the deploy target (`os environments use-runtime`), `os deploy` installs through `os package install` run in the same process. When an `isolated`-posture runtime stops the install on the app's installation-wide (`unique: 'global'`) constraints (`UNIQUE_SCOPE_CONFIRMATION_REQUIRED`), the retry it prints is `os deploy --confirm-global-uniques`, but `os deploy` did not declare that flag: following the printed advice was refused as an unknown flag, and the deploy had no way to pass the confirmation.
11
+
-**What changes.**`os deploy` declares `--confirm-global-uniques` and passes it through to the install, as it already does `--confirm-access-upgrade` and `--confirm-upgrade`: all three go through one seam, to the install only (the dry run sends none, as before). Named while the target is ObjectOS Cloud, it is refused before anything is built or sent, like the two upgrade confirmations.
12
+
-**What does not change.**`os package install --confirm-global-uniques` and the two upgrade confirmations behave as before.
Copy file name to clipboardExpand all lines: content/docs/deployment/cli.mdx
+8-5Lines changed: 8 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3241,6 +3241,7 @@ is its production, so a deploy is always a deliberate act.
3241
3241
| `--wait-timeout <seconds>` | — | How long to wait for the environment to serve the new version (default `600`) |
3242
3242
| `-s, --server <url>` | `OS_CLOUD_URL` | Control-plane URL. Default `https://cloud.objectos.ai`, or the URL recorded by `os cloud login` |
3243
3243
| `-t, --token <key>` | `OS_CLOUD_API_KEY` | Bearer token; `$OS_TOKEN` and `~/.objectstack/cloud.json` are the fallbacks |
3244
+
| `--confirm-global-uniques` | — | Self-hosted target only: confirm the app's installation-wide `unique` constraints are genuinely platform-wide when the runtime's refusal asks (as [`os package install`](#os-package-install)). Refused when the target is ObjectOS Cloud |
3244
3245
| `--confirm-access-upgrade <token>` | — | Self-hosted target only: confirm the upgrade's access findings with the finding-set token the runtime's refusal printed (as [`os package install`](#os-package-install)). Refused when the target is ObjectOS Cloud |
3245
3246
| `--confirm-upgrade <token>` | — | Self-hosted target only: confirm the upgrade's schema findings (a suspected rename, a type change that is not safe) with the finding-set token the runtime's refusal printed (as [`os package install`](#os-package-install)). Refused when the target is ObjectOS Cloud |
3246
3247
@@ -3263,11 +3264,13 @@ answers are the ones printed.
3263
3264
build is printed; nothing is installed. A runtime that refuses it, or does not
3264
3265
serve install-local, stops the deploy with exit `1`. A runtime that predates the
3265
3266
dry run ignores it and installs: the command says so and exits `1`.
3266
-
3. **Install** — with `--confirm-access-upgrade` and `--confirm-upgrade` passed
3267
-
through. The endpoint's refusals (an access upgrade to confirm, a schema
3268
-
upgrade to confirm, a package the running kernel cannot register, …) stop the
3269
-
deploy with exit `1`. An upgrade refusal prints its retry as
3270
-
`os deploy --confirm-access-upgrade <token>`for access findings or
3267
+
3. **Install** — with `--confirm-global-uniques`, `--confirm-access-upgrade` and
3268
+
`--confirm-upgrade` passed through. The endpoint's refusals (installation-wide
3269
+
uniques to confirm on an `isolated` runtime, an access upgrade to confirm, a
3270
+
schema upgrade to confirm, a package the running kernel cannot register, …)
3271
+
stop the deploy with exit `1`, and the retry they print names `os deploy`:
0 commit comments