Skip to content

Commit 4b03f30

Browse files
committed
fix(metadata-protocol): the draft-overlay preview naming no package serves the draft the strict read serves
Claude-Session: https://claude.ai/code/session_01HTBbFnY86QT5g7BxeMo3Ub Co-authored-by: Claude <noreply@anthropic.com>
1 parent e838e9a commit 4b03f30

2 files changed

Lines changed: 23 additions & 9 deletions

File tree

‎packages/metadata-protocol/src/protocol.packageless-save-address.test.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,9 @@ describe('[#23715] the strict draft read naming no package serves its content fr
13001300
const again = await readDraft(f);
13011301
expect(again.item.label).toBe('edited');
13021302
expect(again.version).toBe(saved.version);
1303+
// The draft-overlay preview naming no package serves the same draft.
1304+
expect((await f.protocol.getMetaItem({ type: 'app', name: f.name, previewDrafts: true })).item)
1305+
.toMatchObject({ label: 'edited', _draft: true });
13031306
});
13041307
}
13051308

‎packages/metadata-protocol/src/protocol.ts‎

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10915,12 +10915,13 @@ export class ObjectStackProtocolImplementation implements
1091510915
// package, so with drafts `[package-unbound, Q]` this read served the
1091610916
// first draft row the store returned under the package-unbound
1091710917
// draft's token, and a save pinned to that token wrote a row other
10918-
// than the one read (#8907).
10919-
const strictDraftAddress = readState === 'draft' && !request.packageId
10918+
// than the one read (#8907). The draft-overlay preview below shares
10919+
// the address: it serves the draft the strict read serves.
10920+
const draftContentAddress = !request.packageId && (readState === 'draft' || request.previewDrafts)
1092010921
? await this.strictDraftReadAddress(request.type, request.name, member)
1092110922
: undefined;
1092210923
const contentPackageId = request.packageId
10923-
|| (strictDraftAddress ? undefined : await this.packagelessReadAddress(request.type, request.name, member));
10924+
|| (readState === 'draft' ? undefined : await this.packagelessReadAddress(request.type, request.name, member));
1092410925

1092510926
// ADR-0033 draft-overlay preview (non-strict): when the caller opts in
1092610927
// (admin-gated upstream), prefer a `state='draft'` row if one exists, else
@@ -10933,13 +10934,22 @@ export class ObjectStackProtocolImplementation implements
1093310934
// [#21716] The served-row resolution, on the draft partition
1093410935
// (ADR-0048 prefer-local, parity with the row read below) — see
1093510936
// {@link findServedOverlayRow}.
10936-
const draftRec = (await this.findServedOverlayRow({
10937+
let draftRec = (await this.findServedOverlayRow({
1093710938
type: request.type,
1093810939
name: request.name,
1093910940
state: 'draft',
10940-
...(contentPackageId ? { packageId: contentPackageId } : {}),
10941+
...(draftContentAddress
10942+
? { packageId: draftContentAddress.packageId }
10943+
: contentPackageId ? { packageId: contentPackageId } : {}),
1094110944
...memberOption(member),
1094210945
}))?.row;
10946+
// [#23715] Two or more packages and no package-unbound draft:
10947+
// the best-effort first match, as the strict read below.
10948+
if (!draftRec && draftContentAddress?.bestEffort) {
10949+
draftRec = (await this.findServedOverlayRow({
10950+
type: request.type, name: request.name, state: 'draft', ...memberOption(member),
10951+
}))?.row;
10952+
}
1094310953
if (draftRec) {
1094410954
const draftItem = this.convertStoredItem(
1094510955
String(draftRec.type ?? request.type),
@@ -10983,16 +10993,16 @@ export class ObjectStackProtocolImplementation implements
1098310993
type: request.type,
1098410994
name: request.name,
1098510995
state: readState,
10986-
...(strictDraftAddress
10987-
? { packageId: strictDraftAddress.packageId }
10996+
...(readState === 'draft' && draftContentAddress
10997+
? { packageId: draftContentAddress.packageId }
1098810998
: contentPackageId ? { packageId: contentPackageId } : {}),
1098910999
...memberOption(member),
1099011000
}))?.row;
1099111001
// [#23715] Two or more packages and no package-unbound draft: the
1099211002
// best-effort first match ADR-0048 §3.3 states, as before, served
1099311003
// with `version: null` (no row at the address the save naming none
1099411004
// resolves, and that save is refused there).
10995-
if (!record && strictDraftAddress?.bestEffort) {
11005+
if (!record && readState === 'draft' && draftContentAddress?.bestEffort) {
1099611006
record = (await this.findServedOverlayRow({
1099711007
type: request.type,
1099811008
name: request.name,
@@ -19071,7 +19081,8 @@ export class ObjectStackProtocolImplementation implements
1907119081

1907219082
/**
1907319083
* [#23715, ADR-0048, ADR-0070 TL;DR 1] The package the strict draft read
19074-
* that names no package (`?state=draft`) takes its CONTENT from: the draft
19084+
* that names no package (`?state=draft`), and the draft-overlay preview
19085+
* naming none (`previewDrafts`), take their draft CONTENT from: the draft
1907519086
* its `version` names ({@link readVersionToken}, through
1907619087
* `SysMetadataRepository.headAt`), which is the draft
1907719088
* {@link packagelessDraftAddress} gives the draft save, the per-item

0 commit comments

Comments
 (0)