feat(tree): complete rust family runtime checklist

- add tree shell runtime artifact contracts and page/filetree/picker runtime reducers
- sink tree.subtree.move write operation through Rust and formalize command event plans
- harden file tree search projection contract and route thin-proxy boundaries
- record completed harness tasks and move design docs into process/done
This commit is contained in:
lix-2026
2026-04-27 10:27:15 +08:00
parent e564dfde02
commit 4ab36a9386
30 changed files with 2502 additions and 432 deletions
@@ -21,6 +21,14 @@ export type DocumentMoveOrderPlan = {
patches: DocumentMoveOrderPatch[];
};
export type DocumentMoveWriteOperation = DocumentMoveOrderPlan & {
family: "tree";
schema: "mnote.tree.write_operation";
schemaVersion: 1;
operation: "tree.subtree.move.write";
workspaceId: string;
};
function normalizeParentId(value: string | null | undefined): string | null {
const trimmed = typeof value === "string" ? value.trim() : "";
return trimmed.length > 0 ? trimmed : null;
@@ -121,7 +129,7 @@ export function buildDocumentMoveOrderPlanFromDocuments(input: {
};
}
function normalizePlan(value: unknown): DocumentMoveOrderPlan | null {
export function normalizeDocumentMoveOrderPlan(value: unknown): DocumentMoveOrderPlan | null {
if (!value || typeof value !== "object" || Array.isArray(value)) {
return null;
}
@@ -152,8 +160,37 @@ function normalizePlan(value: unknown): DocumentMoveOrderPlan | null {
};
}
export function assertDocumentMoveOrderPlanMatches(expected: unknown, actual: DocumentMoveOrderPlan) {
const normalizedExpected = normalizePlan(expected);
export function normalizeDocumentMoveWriteOperation(value: unknown): DocumentMoveWriteOperation | null {
if (!value || typeof value !== "object" || Array.isArray(value)) {
return null;
}
const record = value as Partial<DocumentMoveWriteOperation>;
if (
record.family !== "tree" ||
record.schema !== "mnote.tree.write_operation" ||
record.schemaVersion !== 1 ||
record.operation !== "tree.subtree.move.write" ||
typeof record.workspaceId !== "string" ||
!record.workspaceId.trim()
) {
return null;
}
const normalizedPlan = normalizeDocumentMoveOrderPlan(value);
if (!normalizedPlan) {
return null;
}
return {
family: "tree",
schema: "mnote.tree.write_operation",
schemaVersion: 1,
operation: "tree.subtree.move.write",
workspaceId: record.workspaceId.trim(),
...normalizedPlan,
};
}
export function assertDocumentMoveOrderPlanMatches(expected: unknown, actual: DocumentMoveOrderPlan): DocumentMoveOrderPlan {
const normalizedExpected = normalizeDocumentMoveOrderPlan(expected);
if (!normalizedExpected) {
throw new Error("Rust move plan 与 Convex 当前排序状态不一致");
}
@@ -161,4 +198,21 @@ export function assertDocumentMoveOrderPlanMatches(expected: unknown, actual: Do
if (JSON.stringify(normalizedExpected) !== JSON.stringify(actual)) {
throw new Error("Rust move plan 与 Convex 当前排序状态不一致");
}
return normalizedExpected;
}
export function assertDocumentMoveWriteOperationMatches(expected: unknown, actual: DocumentMoveOrderPlan): DocumentMoveOrderPlan {
const normalizedExpected = normalizeDocumentMoveWriteOperation(expected);
if (!normalizedExpected) {
throw new Error("Rust move write operation 与 Convex 当前排序状态不一致");
}
const { family: _family, schema: _schema, schemaVersion: _schemaVersion, operation: _operation, workspaceId: _workspaceId, ...expectedPlan } =
normalizedExpected;
if (JSON.stringify(expectedPlan) !== JSON.stringify(actual)) {
throw new Error("Rust move write operation 与 Convex 当前排序状态不一致");
}
return expectedPlan;
}