Repository navigation
Commit 069fd40
fix(metadata-protocol): the strict draft read naming no package serves its content from the draft its version names (#23727)
Fixes #23715
Clause-②: yes
Dev session `session_01HTBbFnY86QT5g7BxeMo3Ub`, dispatched by
`domain:engine` seat 1 (`session_01GP3comALHRcRBixS2TEnLF`), claim
6201610005. Related, not closed here: #23657 / PR #23706 (the draft
save's address, `unboundItemDraftAddress`) and #23495 / PR #23654 (the
three draft doors' address).
## What this does
The strict draft read that names no package (`GET
/api/v1/meta/TYPE/NAME?state=draft`) now takes its **content** from the
draft its **`version`** names: the draft `packagelessDraftAddress` gives
the draft save, the per-item publish and the draft discard naming none.
Before, the content address came from the item's ACTIVE rows
(`packagelessReadAddress`), which name no package for an item never
published into one, so `findServedOverlayRow` took the first draft row
the store returned.
| state (no `?package=`) | content before | content after | `version`
(unchanged) |
|---|---|---|---|
| no active row, drafts `[package-unbound, Q]`, Q's stored first
(in-memory double) | **Q's draft** | package-unbound draft |
package-unbound draft |
| no active row, drafts `[package-unbound, Q]`, unbound stored first |
package-unbound | package-unbound | package-unbound |
| active rows bound to two packages, drafts `[package-unbound, P]`, P's
stored first | **P's draft** | package-unbound draft | package-unbound
draft |
| active rows bound to one package P | P's draft, else the
package-unbound one | unchanged | unchanged |
| no active row, only Q's draft / only a package-unbound draft | that
draft | unchanged | unchanged |
| no active row, drafts bound to Q and R, none package-unbound |
best-effort first row, `version: null` | unchanged (best-effort fallback
kept) | `null` |
- `strictDraftReadAddress` (new private helper in `protocol.ts`) maps
`packagelessDraftAddress` to a content address: the draft's binding,
`null` for the package-unbound draft alone; an `ambiguous` address keeps
the package-unbound draft, else the best-effort first match ADR-0048
§3.3 states.
- `servedOverlayRowCandidates` / `findServedOverlayRow` accept
`packageId: null` = the package-unbound row only. Every existing caller
passes a string or `undefined`, so their candidate order is unchanged.
- **H3, measured:** the draft-overlay preview naming no package
(`previewDrafts`) shared the defective address: with Q's draft stored
first it served `q` while the fixed strict read served `unbound`. It now
takes the same draft address (it carries no `version`). The layered read
(`getMetaItemLayered`) reads ACTIVE rows only, so it has no draft door
to fix.
- **Rider 6200550012:** `PublishMetaItemRequestSchema.packageId`'s
description now carries the "no package-unbound draft" qualifier
`SaveMetaItemRequestSchema.packageId`'s has (PR #23706). Description
only; `content/docs/references/api/protocol.mdx` regenerated by
`check:generated --fix`.
- **No accept set narrows:** no request answered `200` before is refused
now; `?package=` still reaches each package's draft. The write, publish
and discard addresses are not touched.
## Verification (head `eaa4b0ed`)
- **Negative control on `main` (`9e0945cf4`), in-memory double:** the
new `[#23715]` pins, run before the fix: `Tests 2 failed | 4 passed` —
`expected 'q' to be 'unbound'` (Q's draft first) and `expected 'p' to be
'unbound'` (two active packages, P's draft first).
- **better-sqlite3 (REST harness):** all three orders (unbound saved
first, Q's saved first, both seeded Q's first) were already green on
`main`, and stay green: `sys_metadata`'s `(type, name, package_id,
bundle_member)` index returns the NULL-bound row first, so on this store
content and version agreed by index order alone. These pins are positive
pins plus the `If-Match` round trip; the double is the store that
diverged.
- **Ablation** (`scripts/ablation-replace.mjs`, mutation restoring
`main`'s address logic, the suite imports `./protocol.js` from `src`):
`Tests 2 failed | 55 passed (57)` — exactly the two divergence pins;
restore proven (`blob == HEAD`, `git diff HEAD` empty).
- `pnpm --filter @objectstack/metadata-protocol test`: `Test Files 236
passed | 3 skipped`, `Tests 20572 passed | 19 skipped`.
- Draft-door pins from PR #23706 and PR #23654:
`protocol.packageless-save-address.test.ts` +
`sys-metadata-repository.draft-package-inherit.test.ts` `Tests 81
passed`; `meta-draft-head-package-inheritance.test.ts` +
`meta-draft-read-door-census.test.ts` `Tests 30 passed` (against a
rebuilt `metadata-protocol` dist).
- Typecheck: `metadata-protocol`, `spec`, `rest`, each exit 0.
- `pnpm --filter @objectstack/spec check:generated`: `All 14 generated
artifacts are up to date` after `--fix` regenerated `check:docs` alone.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `eaa4b0ed`: 111 commands; `--ran` with
exit codes: `111 derived, 110 run, 1 NOT-MEASURED, 0 UNRUN`. NOT
MEASURED: `pnpm check:dual-build-cjs-loads` (exit 3, PREREQUISITE NOT
MET: needs every package built; CI runs it). Two first-pass exit-3
prerequisites were satisfied and re-run to exit 0:
`check-plugin-teardown-shape.mjs --self-test` (fetched its pinned
fixture commit) and `spec check:skill-examples` (built `client-react`).
## Acceptance notes
- The list's draft-preview merge (`mergePackageAwareOverlay`, the list's
other served-row reader) was not measured for the `[package-unbound, Q]`
shape; it carries no per-item `version`.
- `main` moved three commits after the branch point (rest analytics
refactor, objectql, organizations); none touches this diff's files or
behaviour, and GitHub reports no conflict, so `main` was not merged in.
- Open PRs touching `protocol.ts` at opening: #23704 (D9.9,
`saveMetaItem`) and #23724 (orphan adoption); different regions.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01HTBbFnY86QT5g7BxeMo3Ub)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 534ca13 commit 069fd40
6 files changed
Lines changed: 292 additions & 13 deletions
File tree
- .changeset
- content/docs/references/api
- packages
- metadata-protocol/src
- rest/src
- spec/src/api
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2442 | 2442 | | |
2443 | 2443 | | |
2444 | 2444 | | |
2445 | | - | |
| 2445 | + | |
2446 | 2446 | | |
2447 | 2447 | | |
2448 | 2448 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1240 | 1240 | | |
1241 | 1241 | | |
1242 | 1242 | | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
| 1278 | + | |
| 1279 | + | |
| 1280 | + | |
| 1281 | + | |
| 1282 | + | |
| 1283 | + | |
| 1284 | + | |
| 1285 | + | |
| 1286 | + | |
| 1287 | + | |
| 1288 | + | |
| 1289 | + | |
| 1290 | + | |
| 1291 | + | |
| 1292 | + | |
| 1293 | + | |
| 1294 | + | |
| 1295 | + | |
| 1296 | + | |
| 1297 | + | |
| 1298 | + | |
| 1299 | + | |
| 1300 | + | |
| 1301 | + | |
| 1302 | + | |
| 1303 | + | |
| 1304 | + | |
| 1305 | + | |
| 1306 | + | |
| 1307 | + | |
| 1308 | + | |
| 1309 | + | |
| 1310 | + | |
| 1311 | + | |
| 1312 | + | |
| 1313 | + | |
| 1314 | + | |
| 1315 | + | |
| 1316 | + | |
| 1317 | + | |
| 1318 | + | |
| 1319 | + | |
| 1320 | + | |
| 1321 | + | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
| 1331 | + | |
| 1332 | + | |
| 1333 | + | |
| 1334 | + | |
| 1335 | + | |
| 1336 | + | |
| 1337 | + | |
| 1338 | + | |
| 1339 | + | |
| 1340 | + | |
| 1341 | + | |
| 1342 | + | |
| 1343 | + | |
| 1344 | + | |
| 1345 | + | |
| 1346 | + | |
| 1347 | + | |
| 1348 | + | |
| 1349 | + | |
| 1350 | + | |
| 1351 | + | |
| 1352 | + | |
| 1353 | + | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
| 1360 | + | |
0 commit comments