@earendil-works/pi-agent-core 0.85.1 → 0.86.0
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 +16 -6
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +64 -22
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent.d.ts +5 -3
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +15 -6
- package/dist/agent.js.map +1 -1
- package/dist/harness/config.d.ts +1 -1
- package/dist/harness/config.d.ts.map +1 -1
- package/dist/harness/config.js +10 -2
- package/dist/harness/config.js.map +1 -1
- package/dist/harness/env/nodejs.d.ts +2 -1
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +98 -27
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/execution/tools.d.ts +1 -1
- package/dist/harness/execution/tools.d.ts.map +1 -1
- package/dist/harness/execution/tools.js +0 -2
- package/dist/harness/execution/tools.js.map +1 -1
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js +1 -0
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/pico3/bash.d.ts +10 -0
- package/dist/harness/pico3/bash.d.ts.map +1 -0
- package/dist/harness/pico3/bash.js +25 -0
- package/dist/harness/pico3/bash.js.map +1 -0
- package/dist/harness/pico3/bounded.d.ts +21 -0
- package/dist/harness/pico3/bounded.d.ts.map +1 -0
- package/dist/harness/pico3/bounded.js +98 -0
- package/dist/harness/pico3/bounded.js.map +1 -0
- package/dist/harness/pico3/chord.d.ts +41 -0
- package/dist/harness/pico3/chord.d.ts.map +1 -0
- package/dist/harness/pico3/chord.js +130 -0
- package/dist/harness/pico3/chord.js.map +1 -0
- package/dist/harness/pico3/context.d.ts +16 -0
- package/dist/harness/pico3/context.d.ts.map +1 -0
- package/dist/harness/pico3/context.js +88 -0
- package/dist/harness/pico3/context.js.map +1 -0
- package/dist/harness/pico3/harness.d.ts +197 -0
- package/dist/harness/pico3/harness.d.ts.map +1 -0
- package/dist/harness/pico3/harness.js +654 -0
- package/dist/harness/pico3/harness.js.map +1 -0
- package/dist/harness/pico3/hooks.d.ts +10 -0
- package/dist/harness/pico3/hooks.d.ts.map +1 -0
- package/dist/harness/pico3/hooks.js +33 -0
- package/dist/harness/pico3/hooks.js.map +1 -0
- package/dist/harness/pico3/index.d.ts +19 -0
- package/dist/harness/pico3/index.d.ts.map +1 -0
- package/dist/harness/pico3/index.js +15 -0
- package/dist/harness/pico3/index.js.map +1 -0
- package/dist/harness/pico3/jsonl.d.ts +58 -0
- package/dist/harness/pico3/jsonl.d.ts.map +1 -0
- package/dist/harness/pico3/jsonl.js +325 -0
- package/dist/harness/pico3/jsonl.js.map +1 -0
- package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
- package/dist/harness/pico3/kinds/collapse.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/collapse.js +191 -0
- package/dist/harness/pico3/kinds/collapse.js.map +1 -0
- package/dist/harness/pico3/kinds/entries.d.ts +78 -0
- package/dist/harness/pico3/kinds/entries.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/entries.js +13 -0
- package/dist/harness/pico3/kinds/entries.js.map +1 -0
- package/dist/harness/pico3/kinds/frames.d.ts +9 -0
- package/dist/harness/pico3/kinds/frames.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/frames.js +75 -0
- package/dist/harness/pico3/kinds/frames.js.map +1 -0
- package/dist/harness/pico3/kinds/generation.d.ts +94 -0
- package/dist/harness/pico3/kinds/generation.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/generation.js +504 -0
- package/dist/harness/pico3/kinds/generation.js.map +1 -0
- package/dist/harness/pico3/kinds/job.d.ts +44 -0
- package/dist/harness/pico3/kinds/job.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/job.js +143 -0
- package/dist/harness/pico3/kinds/job.js.map +1 -0
- package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
- package/dist/harness/pico3/kinds/plugin.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/plugin.js +35 -0
- package/dist/harness/pico3/kinds/plugin.js.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.js +145 -0
- package/dist/harness/pico3/kinds/post-tools.js.map +1 -0
- package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
- package/dist/harness/pico3/kinds/task-api.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/task-api.js +45 -0
- package/dist/harness/pico3/kinds/task-api.js.map +1 -0
- package/dist/harness/pico3/kinds/tool.d.ts +43 -0
- package/dist/harness/pico3/kinds/tool.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/tool.js +373 -0
- package/dist/harness/pico3/kinds/tool.js.map +1 -0
- package/dist/harness/pico3/membrane.d.ts +23 -0
- package/dist/harness/pico3/membrane.d.ts.map +1 -0
- package/dist/harness/pico3/membrane.js +141 -0
- package/dist/harness/pico3/membrane.js.map +1 -0
- package/dist/harness/pico3/memory.d.ts +53 -0
- package/dist/harness/pico3/memory.d.ts.map +1 -0
- package/dist/harness/pico3/memory.js +264 -0
- package/dist/harness/pico3/memory.js.map +1 -0
- package/dist/harness/pico3/scheduler.d.ts +46 -0
- package/dist/harness/pico3/scheduler.d.ts.map +1 -0
- package/dist/harness/pico3/scheduler.js +438 -0
- package/dist/harness/pico3/scheduler.js.map +1 -0
- package/dist/harness/pico3/session.d.ts +263 -0
- package/dist/harness/pico3/session.d.ts.map +1 -0
- package/dist/harness/pico3/session.js +1347 -0
- package/dist/harness/pico3/session.js.map +1 -0
- package/dist/harness/pico3/system.d.ts +126 -0
- package/dist/harness/pico3/system.d.ts.map +1 -0
- package/dist/harness/pico3/system.js +244 -0
- package/dist/harness/pico3/system.js.map +1 -0
- package/dist/harness/pico3/types.d.ts +973 -0
- package/dist/harness/pico3/types.d.ts.map +1 -0
- package/dist/harness/pico3/types.js +96 -0
- package/dist/harness/pico3/types.js.map +1 -0
- package/dist/harness/pico3/view.d.ts +34 -0
- package/dist/harness/pico3/view.d.ts.map +1 -0
- package/dist/harness/pico3/view.js +417 -0
- package/dist/harness/pico3/view.js.map +1 -0
- package/dist/harness/runtime/drive/boundary.d.ts.map +1 -1
- package/dist/harness/runtime/drive/boundary.js +6 -3
- package/dist/harness/runtime/drive/boundary.js.map +1 -1
- package/dist/harness/runtime/drive/response.d.ts.map +1 -1
- package/dist/harness/runtime/drive/response.js +4 -4
- package/dist/harness/runtime/drive/response.js.map +1 -1
- package/dist/harness/runtime/drive/retry.d.ts +2 -2
- package/dist/harness/runtime/drive/retry.d.ts.map +1 -1
- package/dist/harness/runtime/drive/retry.js +3 -6
- package/dist/harness/runtime/drive/retry.js.map +1 -1
- package/dist/harness/runtime/drive/structural.d.ts.map +1 -1
- package/dist/harness/runtime/drive/structural.js +5 -5
- package/dist/harness/runtime/drive/structural.js.map +1 -1
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -1
- package/dist/harness/runtime/drive/tool-placement.js +2 -27
- package/dist/harness/runtime/drive/tool-placement.js.map +1 -1
- package/dist/harness/runtime/drive/tools.d.ts.map +1 -1
- package/dist/harness/runtime/drive/tools.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +20 -12
- package/dist/harness/session/fork-policy.d.ts.map +1 -1
- package/dist/harness/session/fork-policy.js +45 -12
- package/dist/harness/session/fork-policy.js.map +1 -1
- package/dist/harness/session/fork.d.ts +0 -2
- package/dist/harness/session/fork.d.ts.map +1 -1
- package/dist/harness/session/fork.js +20 -68
- package/dist/harness/session/fork.js.map +1 -1
- package/dist/harness/session/in-memory-storage-state.d.ts +5 -5
- package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -1
- package/dist/harness/session/in-memory-storage-state.js +99 -39
- package/dist/harness/session/in-memory-storage-state.js.map +1 -1
- package/dist/harness/session/index.d.ts +1 -1
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +1 -1
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/fork.d.ts +38 -0
- package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
- package/dist/harness/session/jsonl/fork.js +264 -0
- package/dist/harness/session/jsonl/fork.js.map +1 -0
- package/dist/harness/session/jsonl/io.d.ts +14 -0
- package/dist/harness/session/jsonl/io.d.ts.map +1 -0
- package/dist/harness/session/jsonl/io.js +86 -0
- package/dist/harness/session/jsonl/io.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +33 -8
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -1
- package/dist/harness/session/jsonl/legacy-v3.js +285 -206
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -1
- package/dist/harness/session/jsonl/repo.d.ts +2 -1
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +36 -20
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +4 -5
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +39 -113
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/memory.d.ts +3 -5
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +9 -14
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/testing/conformance/session-repo.d.ts +2 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -1
- package/dist/harness/session/testing/conformance/session-repo.js +220 -1
- package/dist/harness/session/testing/conformance/session-repo.js.map +1 -1
- package/dist/harness/session/testing/index.d.ts +1 -1
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +1 -1
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/types.d.ts +1 -0
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js.map +1 -1
- package/dist/harness/types.d.ts +14 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/proxy.d.ts +2 -2
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js.map +1 -1
- package/dist/types.d.ts +30 -14
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +10 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { deepStrictEqual, rejects, strictEqual } from "node:assert/strict";
|
|
2
2
|
import { BACKGROUND_CONTEXT } from "../../../context.js";
|
|
3
3
|
import { insertEntry, insertUsage } from "../../commit.js";
|
|
4
|
-
import { appendList, branchTip, entryLabel, laneConfig, laneState, list, operationMeta, operationPreparation, operationResult, operationState, operationToolArgs, pendingEntry, sessionName, setValue, value, } from "../../values.js";
|
|
4
|
+
import { appendList, branchTip, deleteList, entryLabel, laneConfig, laneState, list, operationMeta, operationPreparation, operationResult, operationState, operationToolArgs, pendingEntry, sessionName, setValue, value, } from "../../values.js";
|
|
5
5
|
const ROOT_ID = "00000000-0000-7000-8000-000000000001";
|
|
6
6
|
const CHILD_ID = "00000000-0000-7000-8000-000000000002";
|
|
7
7
|
const SIBLING_ID = "00000000-0000-7000-8000-000000000003";
|
|
@@ -491,6 +491,225 @@ export function createSessionRepoForkBehaviorConformance(backendFactory, onClose
|
|
|
491
491
|
}),
|
|
492
492
|
];
|
|
493
493
|
}
|
|
494
|
+
/** WP08 cases enabled for Memory and JSONL while SQLite's streaming fork implementation is pending. */
|
|
495
|
+
export function createSessionRepoStreamingForkConformance(backendFactory, onClose) {
|
|
496
|
+
// Merge into createSessionRepoForkConformance once SQLite supports these cases.
|
|
497
|
+
return [
|
|
498
|
+
...createSessionRepoForkApplicationListConformance(backendFactory, onClose),
|
|
499
|
+
...createSessionRepoBranchForkApplicationStateConformance(backendFactory, onClose),
|
|
500
|
+
...createSessionRepoForkLaneValidationConformance(backendFactory, onClose),
|
|
501
|
+
];
|
|
502
|
+
}
|
|
503
|
+
function createSessionRepoForkLaneValidationConformance(backendFactory, onClose) {
|
|
504
|
+
const factory = prepareRepoCaseFactory(backendFactory, onClose);
|
|
505
|
+
return [
|
|
506
|
+
createCase(factory, "fork lane validation", "ignores malformed unrelated lanes", async ({ repo }) => {
|
|
507
|
+
const source = await repo.create({ id: "source" }, BACKGROUND_CONTEXT);
|
|
508
|
+
let tree;
|
|
509
|
+
let branch;
|
|
510
|
+
try {
|
|
511
|
+
await source.createBranch("main", null, BACKGROUND_CONTEXT);
|
|
512
|
+
await source.mutate((mutator) => mutator.commit([
|
|
513
|
+
setValue(laneConfig("main"), configuration),
|
|
514
|
+
setValue(laneState("main"), idleLaneState),
|
|
515
|
+
setValue(laneConfig("unrelated"), configuration),
|
|
516
|
+
], BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);
|
|
517
|
+
tree = await repo.fork(source.metadata, { id: "tree", scope: "tree" }, BACKGROUND_CONTEXT);
|
|
518
|
+
branch = await repo.fork(source.metadata, { id: "branch", scope: "branch", branch: "main" }, BACKGROUND_CONTEXT);
|
|
519
|
+
strictEqual(await getBranchTip(branch), null);
|
|
520
|
+
}
|
|
521
|
+
finally {
|
|
522
|
+
await Promise.all([
|
|
523
|
+
source.close(BACKGROUND_CONTEXT),
|
|
524
|
+
tree?.close(BACKGROUND_CONTEXT),
|
|
525
|
+
branch?.close(BACKGROUND_CONTEXT),
|
|
526
|
+
]);
|
|
527
|
+
}
|
|
528
|
+
}),
|
|
529
|
+
];
|
|
530
|
+
}
|
|
531
|
+
/** Creates application-list fork cases. */
|
|
532
|
+
function createSessionRepoForkApplicationListConformance(backendFactory, onClose) {
|
|
533
|
+
const factory = prepareRepoCaseFactory(backendFactory, onClose);
|
|
534
|
+
return ["open", "closed"].flatMap((sourceState) => [
|
|
535
|
+
createCase(factory, `fork application lists (${sourceState} source)`, "tree fork copies lists at distinct addresses", async ({ repo }) => {
|
|
536
|
+
// Each list keeps its own contents: keys "" and "other" in one namespace must not merge.
|
|
537
|
+
// A different namespace also stays separate; pi2.events is application-owned, not reserved.
|
|
538
|
+
const source = await repo.create({ id: "source" }, BACKGROUND_CONTEXT);
|
|
539
|
+
let fork;
|
|
540
|
+
try {
|
|
541
|
+
const events = list("test.application.events");
|
|
542
|
+
const sibling = list(events.namespace, "other");
|
|
543
|
+
const otherNamespace = list("pi2.events");
|
|
544
|
+
const absent = list(events.namespace, "absent");
|
|
545
|
+
await source.appendList(events, "event", BACKGROUND_CONTEXT);
|
|
546
|
+
await source.appendList(sibling, "sibling", BACKGROUND_CONTEXT);
|
|
547
|
+
await source.appendList(otherNamespace, "other namespace", BACKGROUND_CONTEXT);
|
|
548
|
+
if (sourceState === "closed")
|
|
549
|
+
await source.close(BACKGROUND_CONTEXT);
|
|
550
|
+
fork = await repo.fork(source.metadata, { id: "fork", scope: "tree" }, BACKGROUND_CONTEXT);
|
|
551
|
+
deepStrictEqual((await fork.readList(events, undefined, BACKGROUND_CONTEXT)).map(({ value }) => value), ["event"]);
|
|
552
|
+
deepStrictEqual((await fork.readList(sibling, undefined, BACKGROUND_CONTEXT)).map(({ value }) => value), ["sibling"]);
|
|
553
|
+
deepStrictEqual((await fork.readList(otherNamespace, undefined, BACKGROUND_CONTEXT)).map(({ value }) => value), ["other namespace"]);
|
|
554
|
+
deepStrictEqual(await fork.readList(absent, undefined, BACKGROUND_CONTEXT), []);
|
|
555
|
+
}
|
|
556
|
+
finally {
|
|
557
|
+
await Promise.all([source.close(BACKGROUND_CONTEXT), fork?.close(BACKGROUND_CONTEXT)]);
|
|
558
|
+
}
|
|
559
|
+
}),
|
|
560
|
+
createCase(factory, `fork application lists (${sourceState} source)`, "tree fork copies only survivors after list deletion and reappend", async ({ repo }) => {
|
|
561
|
+
// Append old -> delete -> append new must copy only new, even when changes share a transaction.
|
|
562
|
+
// A list deleted without a later append must remain empty in the fork.
|
|
563
|
+
const source = await repo.create({ id: "source" }, BACKGROUND_CONTEXT);
|
|
564
|
+
let fork;
|
|
565
|
+
try {
|
|
566
|
+
const events = list("test.application.events");
|
|
567
|
+
const deleted = list(events.namespace, "deleted");
|
|
568
|
+
await source.appendList(events, "old", BACKGROUND_CONTEXT);
|
|
569
|
+
await source.appendList(deleted, "removed", BACKGROUND_CONTEXT);
|
|
570
|
+
await source.mutate((mutator) => mutator.commit([
|
|
571
|
+
deleteList(events),
|
|
572
|
+
appendList(events, "temporary"),
|
|
573
|
+
deleteList(events),
|
|
574
|
+
appendList(events, "first survivor"),
|
|
575
|
+
deleteList(deleted),
|
|
576
|
+
], BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);
|
|
577
|
+
await source.appendList(events, "second survivor", BACKGROUND_CONTEXT);
|
|
578
|
+
if (sourceState === "closed")
|
|
579
|
+
await source.close(BACKGROUND_CONTEXT);
|
|
580
|
+
fork = await repo.fork(source.metadata, { id: "fork", scope: "tree" }, BACKGROUND_CONTEXT);
|
|
581
|
+
deepStrictEqual((await fork.readList(events, undefined, BACKGROUND_CONTEXT)).map(({ value }) => value), ["first survivor", "second survivor"]);
|
|
582
|
+
deepStrictEqual(await fork.readList(deleted, undefined, BACKGROUND_CONTEXT), []);
|
|
583
|
+
}
|
|
584
|
+
finally {
|
|
585
|
+
await Promise.all([source.close(BACKGROUND_CONTEXT), fork?.close(BACKGROUND_CONTEXT)]);
|
|
586
|
+
}
|
|
587
|
+
}),
|
|
588
|
+
createCase(factory, `fork application lists (${sourceState} source)`, "tree fork preserves list element sequences including gaps", async ({ repo }) => {
|
|
589
|
+
// Other writes consume sequences too. List elements at seq 2 and 4 must stay at 2 and 4
|
|
590
|
+
// in the fork, not be renumbered to 1 and 2.
|
|
591
|
+
const source = await repo.create({ id: "source" }, BACKGROUND_CONTEXT);
|
|
592
|
+
let fork;
|
|
593
|
+
try {
|
|
594
|
+
const events = list("test.application.events");
|
|
595
|
+
const committed = await source.mutate((mutator) => mutator.commit([
|
|
596
|
+
setValue(sessionName, "before"),
|
|
597
|
+
appendList(events, "first"),
|
|
598
|
+
setValue(sessionName, "between"),
|
|
599
|
+
appendList(events, "second"),
|
|
600
|
+
], BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);
|
|
601
|
+
if (sourceState === "closed")
|
|
602
|
+
await source.close(BACKGROUND_CONTEXT);
|
|
603
|
+
fork = await repo.fork(source.metadata, { id: "fork", scope: "tree" }, BACKGROUND_CONTEXT);
|
|
604
|
+
deepStrictEqual(await fork.readList(events, undefined, BACKGROUND_CONTEXT), [
|
|
605
|
+
{ seq: committed.seqs[1], value: "first" },
|
|
606
|
+
{ seq: committed.seqs[3], value: "second" },
|
|
607
|
+
]);
|
|
608
|
+
}
|
|
609
|
+
finally {
|
|
610
|
+
await Promise.all([source.close(BACKGROUND_CONTEXT), fork?.close(BACKGROUND_CONTEXT)]);
|
|
611
|
+
}
|
|
612
|
+
}),
|
|
613
|
+
...["asc", "desc"].map((order) => createCase(factory, `fork application lists (${sourceState} source)`, `tree fork continues ${order} pagination using source cursors`, async ({ repo }) => {
|
|
614
|
+
// A cursor from the source must resume at the same place in the fork. After reading
|
|
615
|
+
// [first, second] ascending, continue with [third]; descending does the reverse.
|
|
616
|
+
// Continuing after the final element must return an empty page, not repeat that element.
|
|
617
|
+
const source = await repo.create({ id: "source" }, BACKGROUND_CONTEXT);
|
|
618
|
+
let fork;
|
|
619
|
+
try {
|
|
620
|
+
const events = list("test.application.events");
|
|
621
|
+
for (const item of ["first", "second", "third"]) {
|
|
622
|
+
await source.appendList(events, item, BACKGROUND_CONTEXT);
|
|
623
|
+
}
|
|
624
|
+
const firstPage = await source.readList(events, { order, limit: 2 }, BACKGROUND_CONTEXT);
|
|
625
|
+
strictEqual(firstPage.length, 2);
|
|
626
|
+
const cursor = { seq: firstPage[1].seq };
|
|
627
|
+
const lastPage = await source.readList(events, { order, cursor, limit: 2 }, BACKGROUND_CONTEXT);
|
|
628
|
+
deepStrictEqual(lastPage.map(({ value }) => value), [order === "asc" ? "third" : "first"]);
|
|
629
|
+
const endCursor = { seq: lastPage[0].seq };
|
|
630
|
+
if (sourceState === "closed")
|
|
631
|
+
await source.close(BACKGROUND_CONTEXT);
|
|
632
|
+
fork = await repo.fork(source.metadata, { id: "fork", scope: "tree" }, BACKGROUND_CONTEXT);
|
|
633
|
+
deepStrictEqual(await fork.readList(events, { order, limit: 2 }, BACKGROUND_CONTEXT), firstPage);
|
|
634
|
+
deepStrictEqual(await fork.readList(events, { order, cursor, limit: 2 }, BACKGROUND_CONTEXT), lastPage);
|
|
635
|
+
deepStrictEqual(await fork.readList(events, { order, cursor: endCursor, limit: 2 }, BACKGROUND_CONTEXT), []);
|
|
636
|
+
}
|
|
637
|
+
finally {
|
|
638
|
+
await Promise.all([source.close(BACKGROUND_CONTEXT), fork?.close(BACKGROUND_CONTEXT)]);
|
|
639
|
+
}
|
|
640
|
+
})),
|
|
641
|
+
]);
|
|
642
|
+
}
|
|
643
|
+
/** Creates branch application-state cases. */
|
|
644
|
+
function createSessionRepoBranchForkApplicationStateConformance(backendFactory, onClose) {
|
|
645
|
+
const factory = prepareRepoCaseFactory(backendFactory, onClose);
|
|
646
|
+
return ["open", "closed"].flatMap((sourceState) => [
|
|
647
|
+
createCase(factory, `branch fork application state (${sourceState} source)`, "excludes overwritten and unchanged application values", async ({ repo }) => {
|
|
648
|
+
// WP08 §1.1: set v1 -> fork point -> overwrite with v2. A branch fork copies neither
|
|
649
|
+
// version: it cannot reconstruct v1 and must not copy v2. Even unchanged older values
|
|
650
|
+
// are excluded, so filtering current values by the fork point's sequence is not enough.
|
|
651
|
+
const source = await repo.create({ id: "source" }, BACKGROUND_CONTEXT);
|
|
652
|
+
let fork;
|
|
653
|
+
try {
|
|
654
|
+
const state = value("test.application.state");
|
|
655
|
+
const unchanged = value("test.application.settings");
|
|
656
|
+
const branch = await source.createBranch("review", null, BACKGROUND_CONTEXT);
|
|
657
|
+
await source.mutate((mutator) => mutator.commit([
|
|
658
|
+
setValue(laneConfig("review"), configuration),
|
|
659
|
+
setValue(laneState("review"), idleLaneState),
|
|
660
|
+
setValue(state, "v1"),
|
|
661
|
+
setValue(unchanged, "predates fork point"),
|
|
662
|
+
], BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);
|
|
663
|
+
const entryId = await branch.appendCustomEntry("fork-point", undefined, BACKGROUND_CONTEXT);
|
|
664
|
+
await source.setValue(state, "v2", BACKGROUND_CONTEXT);
|
|
665
|
+
strictEqual((await source.getValue(state, BACKGROUND_CONTEXT))?.value, "v2");
|
|
666
|
+
if (sourceState === "closed")
|
|
667
|
+
await source.close(BACKGROUND_CONTEXT);
|
|
668
|
+
fork = await repo.fork(source.metadata, { scope: "branch", branch: "review", entryId }, BACKGROUND_CONTEXT);
|
|
669
|
+
strictEqual(await getBranchTip(fork, "review"), entryId);
|
|
670
|
+
strictEqual(await fork.getValue(state, BACKGROUND_CONTEXT), undefined);
|
|
671
|
+
// A survivor older than the fork point must also be excluded, not copied by a seq cutoff.
|
|
672
|
+
strictEqual(await fork.getValue(unchanged, BACKGROUND_CONTEXT), undefined);
|
|
673
|
+
}
|
|
674
|
+
finally {
|
|
675
|
+
await Promise.all([source.close(BACKGROUND_CONTEXT), fork?.close(BACKGROUND_CONTEXT)]);
|
|
676
|
+
}
|
|
677
|
+
}),
|
|
678
|
+
createCase(factory, `branch fork application state (${sourceState} source)`, "excludes deleted/reappended and untouched application lists", async ({ repo }) => {
|
|
679
|
+
// WP08 §1.1: append old -> fork point -> delete -> append new. A branch fork copies
|
|
680
|
+
// neither the deleted elements nor the new ones. A separate untouched list is also
|
|
681
|
+
// excluded, even though its elements still survive from before the fork point.
|
|
682
|
+
const source = await repo.create({ id: "source" }, BACKGROUND_CONTEXT);
|
|
683
|
+
let fork;
|
|
684
|
+
try {
|
|
685
|
+
const events = list("test.application.events");
|
|
686
|
+
const untouched = list(events.namespace, "untouched");
|
|
687
|
+
const branch = await source.createBranch("review", null, BACKGROUND_CONTEXT);
|
|
688
|
+
await source.mutate((mutator) => mutator.commit([
|
|
689
|
+
setValue(laneConfig("review"), configuration),
|
|
690
|
+
setValue(laneState("review"), idleLaneState),
|
|
691
|
+
appendList(events, "old first"),
|
|
692
|
+
appendList(events, "old second"),
|
|
693
|
+
appendList(untouched, "predates fork point"),
|
|
694
|
+
], BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);
|
|
695
|
+
const entryId = await branch.appendCustomEntry("fork-point", undefined, BACKGROUND_CONTEXT);
|
|
696
|
+
await source.deleteList(events, BACKGROUND_CONTEXT);
|
|
697
|
+
await source.appendList(events, "new", BACKGROUND_CONTEXT);
|
|
698
|
+
deepStrictEqual((await source.readList(events, undefined, BACKGROUND_CONTEXT)).map(({ value }) => value), ["new"]);
|
|
699
|
+
if (sourceState === "closed")
|
|
700
|
+
await source.close(BACKGROUND_CONTEXT);
|
|
701
|
+
fork = await repo.fork(source.metadata, { scope: "branch", branch: "review", entryId }, BACKGROUND_CONTEXT);
|
|
702
|
+
strictEqual(await getBranchTip(fork, "review"), entryId);
|
|
703
|
+
deepStrictEqual(await fork.readList(events, undefined, BACKGROUND_CONTEXT), []);
|
|
704
|
+
// Even elements still surviving from before the fork point are excluded.
|
|
705
|
+
deepStrictEqual(await fork.readList(untouched, undefined, BACKGROUND_CONTEXT), []);
|
|
706
|
+
}
|
|
707
|
+
finally {
|
|
708
|
+
await Promise.all([source.close(BACKGROUND_CONTEXT), fork?.close(BACKGROUND_CONTEXT)]);
|
|
709
|
+
}
|
|
710
|
+
}),
|
|
711
|
+
]);
|
|
712
|
+
}
|
|
494
713
|
/** Creates fork cases that require destination reservation across create and fork. */
|
|
495
714
|
export function createSessionRepoForkDestinationReservationConformance(backendFactory, onClose) {
|
|
496
715
|
const factory = prepareRepoCaseFactory(backendFactory, onClose);
|