@melite/estate-drafts 0.1.4-alpha → 0.1.5-pre-alpha
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/README.md +56 -0
- package/lib/bench.d.ts +48 -1
- package/lib/bench.js +87 -12
- package/lib/index.d.ts +4 -1
- package/lib/index.js +5 -1
- package/lib/remote.d.ts +29 -10
- package/lib/remote.js +347 -156
- package/lib/spec.d.ts +28 -1
- package/lib/spec.js +32 -2
- package/lib/store.d.ts +39 -5
- package/lib/store.js +130 -42
- package/lib/trail.d.ts +16 -0
- package/lib/trail.js +91 -0
- package/lib/typert.host.js +24 -21
- package/lib/typert.remote-client.js +15 -15
- package/package.json +7 -3
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: The drafts and bench Typert remote owner — draft docs in a storage domain plus the shared bench mutation surface, mounted as host Cordis services.
|
|
3
|
+
kind: package-library
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @melite/estate-drafts
|
|
7
|
+
|
|
8
|
+
`@melite/estate-drafts` owns the composer's draft docs and the shared bench.
|
|
9
|
+
It mounts the drafts storage-domain seat, `DraftsRemoteService`, and
|
|
10
|
+
`BenchRemoteService` on the host fiber; the host's typert gateway claims the
|
|
11
|
+
endpoints through its discovery walk, and the storage facility arrives via
|
|
12
|
+
the host's storageDomain seat (lazy open on first call). The estate bundle
|
|
13
|
+
mounts it before the runs registry, whose submit gate re-uses this package's
|
|
14
|
+
draft-id law.
|
|
15
|
+
|
|
16
|
+
## Contract
|
|
17
|
+
|
|
18
|
+
- Storage: table `docs` keyed by draft id (`DRAFT_ID_RE`: 1..96 chars of
|
|
19
|
+
`[A-Za-z0-9_-]`, path-safe — the SSOT the queue re-exports).
|
|
20
|
+
Schema-failing records are backed up and skipped; the global slot holds
|
|
21
|
+
the one-time legacy-import marker.
|
|
22
|
+
- Draft docs: six contract keys (`draft_id`, `status`, `createdAt`,
|
|
23
|
+
`completedAt`, `intent`, `stages`) plus caller extras verbatim — the serve
|
|
24
|
+
read is deliberately loose; the write doors are strict.
|
|
25
|
+
- Bench: `ensure`, `get`, `patch`, `add-stage`, `remove-stage`, `reorder`,
|
|
26
|
+
`group`, `rewire`, `undo`, `clear`, keyed by the caller's session key,
|
|
27
|
+
with change notification through the bench change seam.
|
|
28
|
+
- Failures are the protocol's ONE RemoteError with `draft/*` and `bench/*`
|
|
29
|
+
codes declared next to their throws.
|
|
30
|
+
- Declared exports: `.` (plugin + services), `./types` (shared row types),
|
|
31
|
+
`./typert` (generated host-face declaration), `./remote` (generated
|
|
32
|
+
browser client), `./package.json`.
|
|
33
|
+
|
|
34
|
+
## Model Experience
|
|
35
|
+
|
|
36
|
+
### Request context and condition
|
|
37
|
+
|
|
38
|
+
#### What the model sees
|
|
39
|
+
|
|
40
|
+
None — the package contributes no model-visible input.
|
|
41
|
+
|
|
42
|
+
#### Token effect
|
|
43
|
+
|
|
44
|
+
Zero-direct token effect.
|
|
45
|
+
|
|
46
|
+
#### KV Cache effect
|
|
47
|
+
|
|
48
|
+
Independent — no conversation state.
|
|
49
|
+
|
|
50
|
+
## Known Limitations and Deferred Work
|
|
51
|
+
|
|
52
|
+
- **Bench access is session-key scoped** — a caller outside the editor's
|
|
53
|
+
session model must carry the session key itself; there is no cross-session
|
|
54
|
+
bench view.
|
|
55
|
+
- **The loose serve read is deliberate** — extras ride back unvalidated; a
|
|
56
|
+
writer bug can land extras the read will not catch.
|
package/lib/bench.d.ts
CHANGED
|
@@ -48,6 +48,15 @@ declare module "@deepseek-ai/dsh-typert-protocol" {
|
|
|
48
48
|
readonly session: string;
|
|
49
49
|
readonly stage: string;
|
|
50
50
|
};
|
|
51
|
+
/** The anchored reorder's target is gone (the F1-residue cure,
|
|
52
|
+
* round 25): the id the drop named as its anchor is not on the
|
|
53
|
+
* CURRENT list — a second author removed it between the press
|
|
54
|
+
* and the apply. The honest re-ask, never a silent fallback to
|
|
55
|
+
* the stale numeric slot. */
|
|
56
|
+
"bench/anchor-gone": {
|
|
57
|
+
readonly session: string;
|
|
58
|
+
readonly anchor: string;
|
|
59
|
+
};
|
|
51
60
|
|
|
52
61
|
|
|
53
62
|
|
|
@@ -188,7 +197,7 @@ export interface BenchPatchRow {
|
|
|
188
197
|
|
|
189
198
|
|
|
190
199
|
|
|
191
|
-
export declare function patchBench(drafts: Domain<DraftsDomainSpec>, session: string, body: Record<string, unknown>, admit?: StageAdmission): Promise<BenchPatchRow>;
|
|
200
|
+
export declare function patchBench(drafts: Domain<DraftsDomainSpec>, session: string, body: Record<string, unknown>, admit?: StageAdmission, migrate?: LaneMigration): Promise<BenchPatchRow>;
|
|
192
201
|
/** The stage row: the arm's answer (stage id + rev). */
|
|
193
202
|
export interface BenchStageRow {
|
|
194
203
|
readonly draft_id: string;
|
|
@@ -217,12 +226,37 @@ export type StageAdmission = (card: string, params: Record<string, unknown>, pro
|
|
|
217
226
|
|
|
218
227
|
|
|
219
228
|
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
export type LaneMigration = (card: string, params: Record<string, unknown>, priorParams: Record<string, unknown>) => Record<string, unknown>;
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
220
237
|
export declare function strippedForAdmission(card: string, params: Record<string, unknown>): Record<string, unknown>;
|
|
221
238
|
/** The wiring admission over ONE row (params = the MERGED view the
|
|
222
239
|
* next run composes; inputs = the MERGED wiring; liveIds = the
|
|
223
240
|
* bench's stage ids after the write; selfId = the row's own id —
|
|
224
241
|
* self-wiring is a cycle, refused). Throws bench/* named. */
|
|
225
242
|
export declare function admitWiring(row: Record<string, unknown>, params: Record<string, unknown>, inputs: Record<string, unknown>, liveIds: readonly string[], selfId: string, session: string, tolerate?: ReadonlySet<string>): void;
|
|
243
|
+
/** The un-wedge law's tolerance table: for every row in the list
|
|
244
|
+
* being JUDGED, the upstreams it wires that are absent from the
|
|
245
|
+
* PRE-verb live set — refs the verb did not create (they were
|
|
246
|
+
* already dead, or ride a restored snapshot the log itself
|
|
247
|
+
* recorded) and must not be refused for. Keyed by row/child id.
|
|
248
|
+
*
|
|
249
|
+
* The walk is over the JUDGED rows (not the pre rows): a verb
|
|
250
|
+
* like clear leaves no pre rows at all, and undo restores rows
|
|
251
|
+
* the pre state doesn't hold — the ref a row CARRIES is the
|
|
252
|
+
* thing to classify, against what was live before the verb. A
|
|
253
|
+
* ref newly introduced by a verb (rewire's `from`, a patch's
|
|
254
|
+
* spell changes) never rides this table: those seats build their
|
|
255
|
+
* tolerate sets from the PRE ROW's own inputs, so a fresh dead
|
|
256
|
+
* target stays strict. */
|
|
257
|
+
/** Exported for the drafts seat (audit S-S1): the un-wedge table is
|
|
258
|
+
* the same law at every author seat. */
|
|
259
|
+
export declare function toleratedByRow(stages: Array<Record<string, unknown>>, preLive: ReadonlySet<string>): Map<string, Set<string>>;
|
|
226
260
|
/** add_stage — append a card stage with optional wiring (the
|
|
227
261
|
* runner's input convention rides the row). */
|
|
228
262
|
export declare function addStageBench(drafts: Domain<DraftsDomainSpec>, session: string, body: Record<string, unknown>, admit?: StageAdmission): Promise<BenchStageRow>;
|
|
@@ -233,6 +267,12 @@ export declare function addStageBench(drafts: Domain<DraftsDomainSpec>, session:
|
|
|
233
267
|
|
|
234
268
|
|
|
235
269
|
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
236
276
|
export declare function reorderBench(drafts: Domain<DraftsDomainSpec>, session: string, body: Record<string, unknown>): Promise<BenchReorderRow>;
|
|
237
277
|
/** The reorder row: the move's coordinates for the caller's optimistic
|
|
238
278
|
* update (from → to, both POST-splice-clamp). */
|
|
@@ -309,6 +349,13 @@ export interface BenchChangeSeam {
|
|
|
309
349
|
/** Install the seam (the plugin does this with its Context; tests do
|
|
310
350
|
* it with their own). Pass null to detach. */
|
|
311
351
|
export declare function setBenchChangeSeam(seam: BenchChangeSeam | null): void;
|
|
352
|
+
/** Detach the seam ONLY if `seam` is still the installed one — the
|
|
353
|
+
* ownership stamp that keeps dispose honest: a fiber that installed
|
|
354
|
+
* EARLIER (a newer install displaced it) detaches nothing, so the
|
|
355
|
+
* live seam survives the older fiber's unwind.
|
|
356
|
+
* @param seam - the seam instance the caller installed.
|
|
357
|
+
*/
|
|
358
|
+
export declare function clearBenchChangeSeam(seam: BenchChangeSeam): void;
|
|
312
359
|
|
|
313
360
|
|
|
314
361
|
|
package/lib/bench.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { unwrapItemArrays } from '@melite/comfyui-card-kit';
|
|
16
16
|
import { benchDraftIdOf, BIRTH_STRIP_KEYS, LOAD_CARRY_KEYS, normalizeBenchStage, SELF_NAMED_FAMILIES, stripKeys } from '@melite/contracts/benchStage';
|
|
17
17
|
import { RemoteError } from "@deepseek-ai/dsh-typert-protocol";
|
|
18
|
+
import { trailDedupe } from "./trail.js";
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
|
|
@@ -438,7 +439,14 @@ export async function ensureBench(drafts, body, admit) {
|
|
|
438
439
|
continue;
|
|
439
440
|
for (const key of MEMORY_KEYS) {
|
|
440
441
|
if (prev[key] !== undefined && row[key] === undefined) {
|
|
441
|
-
|
|
442
|
+
// THE TRAIL HEAL AT CARRY (trail-defect-hunt §6): a memory
|
|
443
|
+
// carry of history passes through the one-row-per-run dedup —
|
|
444
|
+
// a pre-law duplicated trail (the operator's re-add wound,
|
|
445
|
+
// one run under two url spellings) never fossilises forward
|
|
446
|
+
// through load.
|
|
447
|
+
row[key] = key === "history" && Array.isArray(prev[key])
|
|
448
|
+
? trailDedupe(prev[key])
|
|
449
|
+
: prev[key];
|
|
442
450
|
}
|
|
443
451
|
}
|
|
444
452
|
}
|
|
@@ -635,7 +643,7 @@ const PATCH_KEYS = ["stage", "params", "result", "runStatus", "expect_rev", "aut
|
|
|
635
643
|
|
|
636
644
|
|
|
637
645
|
|
|
638
|
-
export async function patchBench(drafts, session, body, admit) {
|
|
646
|
+
export async function patchBench(drafts, session, body, admit, migrate) {
|
|
639
647
|
refuseUnknown(body, PATCH_KEYS);
|
|
640
648
|
if ("result" in body || "runStatus" in body) {
|
|
641
649
|
throw new RemoteError("bench/bad-body", "run outcomes ride the drafts/patch door (result/runStatus refused on the bench verb — it authors params only)", {});
|
|
@@ -704,7 +712,25 @@ export async function patchBench(drafts, session, body, admit) {
|
|
|
704
712
|
// row (a group, an undo) judged a different object than the one
|
|
705
713
|
// on disk. The merge strips before judging AND before storing:
|
|
706
714
|
// one row, one view.
|
|
707
|
-
|
|
715
|
+
|
|
716
|
+
// incident — live on :3088): the merge above is where a lane
|
|
717
|
+
// switch assembles its view, and BEFORE this seat the switch
|
|
718
|
+
// REFUSED itself — the prior lane's members (voice on
|
|
719
|
+
// CustomVoice) ride the merged view, the new lane's surface
|
|
720
|
+
// (VoiceDesign) does not take them, and the admission refused
|
|
721
|
+
// "drop it or switch lane" while the form HIDES the row on the
|
|
722
|
+
// new lane: the named cure unclickable, the switch unlandable,
|
|
723
|
+
// the studio wedged between "the studio shows your edit; the
|
|
724
|
+
// bench does not". The registry drops the stale carry here —
|
|
725
|
+
// BEFORE the strip, the admission, and the store, so the row
|
|
726
|
+
// that lands is the row the next run composes (one view, every
|
|
727
|
+
// seat). The undo contract: undoing the switch restores the
|
|
728
|
+
// axes, not the dropped members — the author re-picks on the
|
|
729
|
+
// lane they return to.
|
|
730
|
+
const migrated = migrate !== undefined && isRecord(st["params"])
|
|
731
|
+
? migrate(typeof st["card"] === "string" ? st["card"] : "", cur, st["params"])
|
|
732
|
+
: cur;
|
|
733
|
+
const stored = strippedForAdmission(typeof st["card"] === "string" ? st["card"] : "", migrated);
|
|
708
734
|
// THE COMPOUND IS JUDGED BY ITS MEMBERS HERE TOO (the walls
|
|
709
735
|
|
|
710
736
|
// belongs to a compound judged the COMPOUND ROW as a whole, and
|
|
@@ -969,7 +995,9 @@ function liveIdsOf(stages) {
|
|
|
969
995
|
* spell changes) never rides this table: those seats build their
|
|
970
996
|
* tolerate sets from the PRE ROW's own inputs, so a fresh dead
|
|
971
997
|
* target stays strict. */
|
|
972
|
-
|
|
998
|
+
/** Exported for the drafts seat (audit S-S1): the un-wedge table is
|
|
999
|
+
* the same law at every author seat. */
|
|
1000
|
+
export function toleratedByRow(stages, preLive) {
|
|
973
1001
|
const out = new Map();
|
|
974
1002
|
const rowOf = (r, id) => {
|
|
975
1003
|
const inputs = r["inputs"];
|
|
@@ -1159,7 +1187,13 @@ export async function addStageBench(drafts, session, body, admit) {
|
|
|
1159
1187
|
return { draft_id: loaded.draftId, session, rev: newRev, stage: stageId };
|
|
1160
1188
|
}
|
|
1161
1189
|
const REMOVE_KEYS = ["stage", "expect_rev", "author"];
|
|
1162
|
-
const REORDER_KEYS = ["stage", "to", "expect_rev", "author"];
|
|
1190
|
+
const REORDER_KEYS = ["stage", "to", "expect_rev", "author", "after"];
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
|
|
1163
1197
|
|
|
1164
1198
|
|
|
1165
1199
|
|
|
@@ -1179,6 +1213,10 @@ export async function reorderBench(drafts, session, body) {
|
|
|
1179
1213
|
if (typeof toRaw !== "number" || !Number.isInteger(toRaw) || toRaw < 0) {
|
|
1180
1214
|
throw new RemoteError("bench/bad-body", "to must be a non-negative integer index", {});
|
|
1181
1215
|
}
|
|
1216
|
+
const afterRaw = body["after"];
|
|
1217
|
+
if (afterRaw !== undefined && typeof afterRaw !== "string") {
|
|
1218
|
+
throw new RemoteError("bench/bad-body", "after must be a stage id string when present", {});
|
|
1219
|
+
}
|
|
1182
1220
|
const author = authorOk(body["author"])
|
|
1183
1221
|
? body["author"]
|
|
1184
1222
|
: "agent";
|
|
@@ -1187,8 +1225,20 @@ export async function reorderBench(drafts, session, body) {
|
|
|
1187
1225
|
if (from < 0) {
|
|
1188
1226
|
throw new RemoteError("bench/stage-not-found", "stage not found: " + stageId, { session, stage: stageId });
|
|
1189
1227
|
}
|
|
1228
|
+
// anchor resolution: re-derive the target from the id the press
|
|
1229
|
+
// SAW, not the numeric slot it guessed. Unchanged list → the same
|
|
1230
|
+
// `to` the press sent (identity, never a behavior change); a
|
|
1231
|
+
// shifted list → the drop's intent survives the shift.
|
|
1232
|
+
let toTarget = toRaw;
|
|
1233
|
+
if (afterRaw !== undefined) {
|
|
1234
|
+
const anchor = stages.findIndex((s) => s["id"] === afterRaw);
|
|
1235
|
+
if (anchor < 0) {
|
|
1236
|
+
throw new RemoteError("bench/anchor-gone", "the card you dropped after is gone — drop again", { session, anchor: afterRaw });
|
|
1237
|
+
}
|
|
1238
|
+
toTarget = anchor;
|
|
1239
|
+
}
|
|
1190
1240
|
const [row] = stages.splice(from, 1);
|
|
1191
|
-
const to = Math.min(
|
|
1241
|
+
const to = Math.min(toTarget, stages.length);
|
|
1192
1242
|
stages.splice(to, 0, row);
|
|
1193
1243
|
loaded.doc["stages"] = stages;
|
|
1194
1244
|
const newRev = await appendAndSave(drafts, loaded, {
|
|
@@ -1196,7 +1246,7 @@ export async function reorderBench(drafts, session, body) {
|
|
|
1196
1246
|
kind: "reorder",
|
|
1197
1247
|
stage: stageId,
|
|
1198
1248
|
summary: "reorder " + String(row["card"] ?? stageId),
|
|
1199
|
-
inverse: { stage: stageId, from, to },
|
|
1249
|
+
inverse: { stage: stageId, from, to, ...(afterRaw !== undefined ? { after: afterRaw } : {}) },
|
|
1200
1250
|
});
|
|
1201
1251
|
return { draft_id: loaded.draftId, session, rev: newRev, stage: stageId, from, to };
|
|
1202
1252
|
}
|
|
@@ -1523,9 +1573,13 @@ const UNDO_KEYS = ["n", "author", "expect_rev"];
|
|
|
1523
1573
|
export async function undoBench(drafts, session, body, admit) {
|
|
1524
1574
|
refuseUnknown(body, UNDO_KEYS);
|
|
1525
1575
|
const loaded = await loadBench(drafts, session);
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1576
|
+
// THE FENCE IS NOT OPTIONAL (audit W-E2): undo reverts writes —
|
|
1577
|
+
// exactly the mutations the CAS law fences. It was the only verb
|
|
1578
|
+
// that skipped the check when expect_rev was absent, so an
|
|
1579
|
+
// un-read revert raced any concurrent writer and silently
|
|
1580
|
+
// double-applied. Same voice as every verb: absent expect_rev
|
|
1581
|
+
// refuses bench/cas-conflict with current_rev.
|
|
1582
|
+
casCheck(loaded.block, body["expect_rev"], session);
|
|
1529
1583
|
const n = typeof body["n"] === "number" &&
|
|
1530
1584
|
Number.isInteger(body["n"]) &&
|
|
1531
1585
|
body["n"] > 0
|
|
@@ -1600,6 +1654,13 @@ export async function undoBench(drafts, session, body, admit) {
|
|
|
1600
1654
|
}
|
|
1601
1655
|
}
|
|
1602
1656
|
const baseIds = liveIdsOf(baseRows);
|
|
1657
|
+
// THE TRAIL HEAL AT UNDO (trail-defect-hunt §6): a reinserted
|
|
1658
|
+
// pre-law row's duplicated history never rides back in — same
|
|
1659
|
+
// dedup the load carry applies.
|
|
1660
|
+
for (const r of stagesOf(undoDoc)) {
|
|
1661
|
+
if (Array.isArray(r["history"]))
|
|
1662
|
+
r["history"] = trailDedupe(r["history"]);
|
|
1663
|
+
}
|
|
1603
1664
|
const restored = stagesOf(undoDoc);
|
|
1604
1665
|
admitWiringList(restored, session, toleratedByRow(restored.filter((r) => baseIds.has(String(r["id"] ?? ""))), baseIds));
|
|
1605
1666
|
})();
|
|
@@ -1828,6 +1889,16 @@ let benchChangeSeam = null;
|
|
|
1828
1889
|
export function setBenchChangeSeam(seam) {
|
|
1829
1890
|
benchChangeSeam = seam;
|
|
1830
1891
|
}
|
|
1892
|
+
/** Detach the seam ONLY if `seam` is still the installed one — the
|
|
1893
|
+
* ownership stamp that keeps dispose honest: a fiber that installed
|
|
1894
|
+
* EARLIER (a newer install displaced it) detaches nothing, so the
|
|
1895
|
+
* live seam survives the older fiber's unwind.
|
|
1896
|
+
* @param seam - the seam instance the caller installed.
|
|
1897
|
+
*/
|
|
1898
|
+
export function clearBenchChangeSeam(seam) {
|
|
1899
|
+
if (benchChangeSeam === seam)
|
|
1900
|
+
benchChangeSeam = null;
|
|
1901
|
+
}
|
|
1831
1902
|
|
|
1832
1903
|
|
|
1833
1904
|
|
|
@@ -1844,8 +1915,12 @@ export function onBenchChange(fn) {
|
|
|
1844
1915
|
try {
|
|
1845
1916
|
fn(session);
|
|
1846
1917
|
}
|
|
1847
|
-
catch {
|
|
1848
|
-
|
|
1918
|
+
catch (listenerError) {
|
|
1919
|
+
// listenerError: the contract keeps a subscriber's fault from
|
|
1920
|
+
// breaking the write, but the fault is not silence — the row
|
|
1921
|
+
// names it like the runs seam's own wrap does
|
|
1922
|
+
console.warn("[estate-drafts] bench change listener refused for session " +
|
|
1923
|
+
JSON.stringify(session) + ":", listenerError);
|
|
1849
1924
|
}
|
|
1850
1925
|
});
|
|
1851
1926
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { Context, Plugin } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { DraftsConfig } from "./store.js";
|
|
2
3
|
export { BenchRemoteService, DraftsRemoteService, installBenchChangeSeam } from "./remote.js";
|
|
3
4
|
export { resolveStorageRoot, openDraftsDomain, } from "./store.js";
|
|
5
|
+
export type { DraftsConfig } from "./store.js";
|
|
4
6
|
export { DRAFT_ID_RE, draftIdOk } from "./spec.js";
|
|
7
|
+
export type { CharacterRecord } from "./spec.js";
|
|
5
8
|
export type { BenchChangeSeam } from "./bench.js";
|
|
6
9
|
export { setBenchChangeSeam } from "./bench.js";
|
|
7
10
|
export type { BenchEnsureRow, BenchGetRow, DraftListResult, DraftListRow, } from "./remote.js";
|
|
8
11
|
export declare const name = "estate-drafts";
|
|
9
|
-
export declare function apply(ctx: Context): void;
|
|
12
|
+
export declare function apply(ctx: Context, config?: DraftsConfig): void;
|
|
10
13
|
declare const plugin: Plugin;
|
|
11
14
|
export default plugin;
|
|
12
15
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { BenchRemoteService, DraftsRemoteService } from "./remote.js";
|
|
2
|
+
import { DraftsDomainSeatService } from "./store.js";
|
|
2
3
|
export { BenchRemoteService, DraftsRemoteService, installBenchChangeSeam } from "./remote.js";
|
|
3
4
|
export { resolveStorageRoot, openDraftsDomain, } from "./store.js";
|
|
4
5
|
export { DRAFT_ID_RE, draftIdOk } from "./spec.js";
|
|
5
6
|
export { setBenchChangeSeam } from "./bench.js";
|
|
6
7
|
export const name = "estate-drafts";
|
|
7
|
-
export function apply(ctx) {
|
|
8
|
+
export function apply(ctx, config = {}) {
|
|
9
|
+
// the domain seat mounts FIRST — the remote services' writers open
|
|
10
|
+
// the drafts domain through it (openDraftsDomain probes this seat)
|
|
11
|
+
new DraftsDomainSeatService(ctx, config);
|
|
8
12
|
new DraftsRemoteService(ctx);
|
|
9
13
|
new BenchRemoteService(ctx);
|
|
10
14
|
}
|
package/lib/remote.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Context } from "@deepseek-ai/cordis";
|
|
|
2
2
|
import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
3
3
|
import { STAGE_PATCH_KEYS, type StagePatchKey } from "@melite/contracts/benchStage";
|
|
4
4
|
export { STAGE_PATCH_KEYS, type StagePatchKey };
|
|
5
|
+
import { type LaneMigration } from "./bench.js";
|
|
5
6
|
import type { BenchEnsureRow, BenchGetRow, BenchPatchRow, BenchReorderRow, BenchRewireRow, BenchClearRow, BenchStageRow, BenchUndoRow } from "./bench.js";
|
|
6
7
|
export type { BenchEnsureRow, BenchGetRow, BenchPatchRow, BenchReorderRow, BenchRewireRow, BenchStageRow, BenchUndoRow, } from "./bench.js";
|
|
7
8
|
/** Endpoint `drafts/patch` answer — the old door's delivered envelope:
|
|
@@ -34,6 +35,11 @@ export interface DraftListResult {
|
|
|
34
35
|
* boundary contains unconstrained unknown data"); open card
|
|
35
36
|
* payloads (stage params, results, history) are honestly JSON all
|
|
36
37
|
* the way down, so the wire face says exactly that. */
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
37
43
|
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
38
44
|
readonly [key: string]: JsonValue;
|
|
39
45
|
};
|
|
@@ -98,6 +104,7 @@ declare module "@deepseek-ai/cordis" {
|
|
|
98
104
|
/**
|
|
99
105
|
* A bench write landed. Emitted after every successful bench verb
|
|
100
106
|
* (and after the drafts-patch door's bench-shaped write).
|
|
107
|
+
* @mode emit
|
|
101
108
|
* @param session - the bench session whose doc changed.
|
|
102
109
|
*/
|
|
103
110
|
"bench.changed": (session: string) => void;
|
|
@@ -121,21 +128,21 @@ declare module "@deepseek-ai/cordis" {
|
|
|
121
128
|
|
|
122
129
|
|
|
123
130
|
|
|
131
|
+
|
|
124
132
|
export declare function installBenchChangeSeam(ctx: Context): () => void;
|
|
125
133
|
/** ── THE OUTPUT HISTORY HELPERS (stroke 40) ──────────────────────
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* same harvest order the client's preview reads — the history and
|
|
129
|
-
* the hero can never disagree about what a run produced). */
|
|
130
|
-
export declare function resultOutputUrls(result: unknown): string[];
|
|
131
|
-
/** Same OUTPUTS (the uniqueness key): two results match when their
|
|
132
|
-
* url sets are equal — a re-run landing the same urls is not a new
|
|
133
|
-
* history entry (the operator's "when it is unique"). */
|
|
134
|
+
* resultOutputUrls now lives in trail.ts (the cycle-free seam) and
|
|
135
|
+
* is re-exported below with the trail laws. ───────────────────── */
|
|
134
136
|
export declare function sameResultOutputs(a: unknown, b: unknown): boolean;
|
|
135
137
|
|
|
136
138
|
|
|
137
139
|
|
|
138
140
|
|
|
141
|
+
export { canonicalOutputUrl, resultOutputUrls, isTerminalTrailWord as isTerminalWord, trailDedupe } from "./trail.js";
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
139
146
|
|
|
140
147
|
|
|
141
148
|
|
|
@@ -191,8 +198,16 @@ export declare function laneAdmissionOf(ctx: Context): ((card: string, params: R
|
|
|
191
198
|
|
|
192
199
|
|
|
193
200
|
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
export declare function laneMigrationOf(ctx: Context): LaneMigration | undefined;
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
194
210
|
export declare function benchAdmissionOf(ctx: Context): ((card: string, params: Record<string, unknown>, provenance: unknown) => void) | undefined;
|
|
195
|
-
/** The drafts Remote owner: list/get over the storage domain. */
|
|
196
211
|
export declare class DraftsRemoteService extends TypertRemoteService {
|
|
197
212
|
|
|
198
213
|
|
|
@@ -240,8 +255,12 @@ export declare class DraftsRemoteService extends TypertRemoteService {
|
|
|
240
255
|
|
|
241
256
|
|
|
242
257
|
remoteExportPatch(draftId: string, stageId: string, patch: DraftStagePatch, expectRev: number | null, signal: AbortSignal): Promise<DraftPatchRow>;
|
|
243
|
-
/** The patch arm the adapter above delegates to
|
|
258
|
+
/** The patch arm the adapter above delegates to — one write
|
|
259
|
+
* transaction on the draft's own key, shared with the bench
|
|
260
|
+
* verbs (the round-14 race audit's R3: the author arm's
|
|
261
|
+
* spread-copy of the log forked against their in-place push). */
|
|
244
262
|
patch(draftId: string, stageId: string, patch: Record<string, unknown>, expectRev: number | null, signal: AbortSignal): Promise<DraftPatchRow>;
|
|
263
|
+
private patchBody;
|
|
245
264
|
}
|
|
246
265
|
/** The bench Remote owner: ensure/get over the same drafts domain
|
|
247
266
|
* (the bench doc IS a draft doc, id "bench-<session>"). */
|