Repository navigation
Commit 6e0e7d7
fix(cli): os package publish names the objectstack.manifest.json keys it does not send (#27368)
domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wgKURKuRGF1ewEVVZKx7U1i4)_
Fixes #27325
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:`os package publish` 读 `objectstack.manifest.json`
时,若文件声明了它不发送的键(`tags`、`publisher`、`isStarter`、`preview`),打印一条警告,说明这些键尚未被托管目录承接,并附云端跟进卡链接;文件里写了
`visibility` 时另打一条,提示改用 `--visibility`。发包照常成功(exit 0)。
- **为什么改**:清单文件的 schema 接受这些键,作者(含 AI)照写,但发包从不发送,目录里什么都看不到,也没有任何提示。按
triage 裁定(路线 B),先结束“静默丢弃”;真正发送这些键要等云端确认接口(跟进卡 #27348)。
- **风险与回滚**:只多打印警告,请求体与退出码都不变;空白模板自带 `isStarter: true`,因此用警告而非拒绝。回滚即还原本
PR。
- **先看**:`packages/cli/src/commands/package/publish.ts` 新增的
`UNCARRIED_MANIFEST_KEYS` 与 `uncarriedManifestWarnings`,以及 `run()`
里读完清单后那一行;`packages/cli/test/package-publish-uncarried-manifest-keys.test.ts`
的键分区测试。
- **两分钟验证**:`pnpm --filter @objectstack/cli exec vitest run --project
unit test/package-publish-uncarried-manifest-keys.test.ts`,预期 5 条全过。
- **需要你做的**:无,席位落地。
## What changes
**The silent path ends.** `objectstack.manifest.json` is validated by
`TemplateManifestSchema`, which accepts `tags`, `publisher`, `isStarter`
and `visibility` (inherited from `CreatePackageRequestSchema`) and the
scaffold-side `preview`. `os package publish` sends none of them, so an
author's listing tags or starter flag never reached the catalog and
nothing said why. Right after publish reads the manifest (the one place
it does), it now prints:
- one warning naming each declared catalog key (`tags`, `publisher`,
`isStarter`, `preview`): declared, but the hosted catalog does not carry
it yet, with a link to #27348, the cloud card that owns the send leg;
- a separate warning for a declared `visibility`, pointing at
`--visibility`, which does carry it today.
The publish still succeeds (exit 0): the bundled blank template ships
`isStarter: true`, so a refusal would break every freshly scaffolded
app.
**Why warn instead of send.** The only receiver of `POST
/api/v1/cloud/packages` is the hosted control plane; no handler lives in
this repo. `CreatePackageRequestSchema` declares the keys, but it is not
provably the route's validator (the wire is snake_case, and publish
already sends a `readme` and a top-level `tagline` the schema lacks).
The read-side row stores `tags` as a string, not an array. `publisher`
is a trust tier that gates listing privileges, so sending an author's
self-declared value is a privilege claim only the control plane can
judge. Triage ruled route (B) here and filed the send leg, the
`publisher` gate and the `tagline` leg as #27348 (comment 6485703694 on
the card). A comment on `UNCARRIED_MANIFEST_KEYS` says not to start
sending them before that card answers.
**The class is guarded.** A test partitions every
`TemplateManifestSchema` key into sent, warned about, or scaffold-only.
A key the schema gains later lands in no bucket and turns the test red
until publish either sends it or names it.
**Not touched.** Nothing under `packages/spec`. The top-level `tagline`
publish sends is unchanged; its leg moved to #27348 per the ruling.
## Tests
New `packages/cli/test/package-publish-uncarried-manifest-keys.test.ts`
(5):
- a manifest declaring `tags`, `publisher`, `isStarter` and `preview`
publishes (both POSTs made); exactly one warning names all four and
links the tracking issue; none of the keys (nor `is_starter`) is on the
request;
- a declared `visibility` gets its own warning naming `--visibility`,
without the tracking link, and is not on the request;
- a manifest with none of them prints no such warning;
- the schema-key partition (sent / warned / scaffold-only) is exact and
disjoint;
- a fixture carrying every warned key parses against
`TemplateManifestSchema`, and the helper reports all of them.
<details><summary>Ablation: the warning call removed, at HEAD
fdecadf</summary>
`node scripts/ablation-replace.mjs --file
packages/cli/src/commands/package/publish.ts --anchor 'for (const
warning of uncarriedManifestWarnings(m)) printWarning(warning);'
--delete -- …vitest…
test/package-publish-uncarried-manifest-keys.test.ts`
```
ablation-replace: ok mutation landed: anchor 1 -> 0, blob 2464b74 -> 1c7b57198a9f
× names each declared catalog key it does not send, points at the tracking issue, and still publishes
× names `visibility` separately, with the flag that does carry it
Tests 2 failed | 3 passed (5)
ablation-replace: ok restored: blob == HEAD (2464b74) and `git diff HEAD` is empty
```
The cli tests import `src/` directly, so no rebuild sits between the
mutation and the run.
</details>
## Acceptance notes
- **Deviation, `visibility`.** The card names `tags`, `publisher` and
`isStarter`; the ruling adds `preview`. `visibility` is the same defect
in the same file (accepted by the manifest schema, silently not read),
so it is in the warned set under the bounded in-place exemption, with
the seat's agreement. Its warning points at the flag rather than at
#27348.
- **`preview`** is a documented scaffold-side key
(`TemplateManifestSchema.preview`, screenshots and demo URL). Publish
has no screenshot upload path, so it is warned about with the catalog
keys, as ruled.
## Verification
Local, at HEAD `fdecadf7`, rebased on `origin/main` `efdf11ae`:
- `pnpm --filter @objectstack/cli exec vitest run --project unit` over
the six publish test files: 72/72 passed. Full cli `unit` layer: 347
files, 5037/5037 passed (lock VERDICT command-exit 0). The `integration`
layer is declared to CI (no spawn entry or integration file touched).
- `pnpm --filter @objectstack/cli typecheck` and `eslint
--no-inline-config` on the two touched files: exit 0.
<details><summary>Derived gates: 62 derived, 61 run, 1 NOT
MEASURED</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `fdecadf7` derived 62 families; all were
run, and `--ran` reconciles 62 accounted, 61 run with exit 0, 1 NOT
MEASURED:
- `pnpm check:dual-build-cjs-loads`: exit 3, PREREQUISITE NOT MET (it
needs the whole workspace built; only the cli closure is built here).
Left to CI.
- `check-plugin-teardown-shape.mjs --self-test` and `check:i18n`,
`check:i18n-coverage`, `check:i18n-walk-parity` first exited 3 (shallow
clone; cli not built). They were re-run after fetching the self-test's
pinned commit and building `@objectstack/cli`, and all four exited 0.
Families CI runs beyond this list are read from this PR's check-runs,
not re-run locally.
</details>
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent c4c515a commit 6e0e7d7
3 files changed
Lines changed: 231 additions & 1 deletion
File tree
- .changeset
- packages/cli
- src/commands/package
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| |||
256 | 256 | | |
257 | 257 | | |
258 | 258 | | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
259 | 318 | | |
260 | 319 | | |
261 | 320 | | |
| |||
450 | 509 | | |
451 | 510 | | |
452 | 511 | | |
| 512 | + | |
453 | 513 | | |
454 | 514 | | |
455 | 515 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
0 commit comments