@avocadostudio-ai/orchestrator-core 0.1.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.
Files changed (196) hide show
  1. package/LICENSE +201 -0
  2. package/dist/agent/agent-context.d.ts +19 -0
  3. package/dist/agent/agent-context.js +67 -0
  4. package/dist/agent/agent-logger.d.ts +5 -0
  5. package/dist/agent/agent-logger.js +22 -0
  6. package/dist/agent/agent-loop-openai.d.ts +8 -0
  7. package/dist/agent/agent-loop-openai.js +172 -0
  8. package/dist/agent/agent-loop.d.ts +56 -0
  9. package/dist/agent/agent-loop.js +167 -0
  10. package/dist/agent/agent-provider.d.ts +28 -0
  11. package/dist/agent/agent-provider.js +63 -0
  12. package/dist/agent/agent-tools.d.ts +28 -0
  13. package/dist/agent/agent-tools.js +899 -0
  14. package/dist/agent/context/editing-guidelines.md +46 -0
  15. package/dist/agent/context/role.md +39 -0
  16. package/dist/agent/integration-prompt.d.ts +9 -0
  17. package/dist/agent/integration-prompt.js +154 -0
  18. package/dist/agent/sites-agent-context.d.ts +12 -0
  19. package/dist/agent/sites-agent-context.js +316 -0
  20. package/dist/agent/sites-agent-shared.d.ts +161 -0
  21. package/dist/agent/sites-agent-shared.js +1101 -0
  22. package/dist/agent/sites-agent-tools.d.ts +18 -0
  23. package/dist/agent/sites-agent-tools.js +1227 -0
  24. package/dist/chat/anthropic-cache.d.ts +20 -0
  25. package/dist/chat/anthropic-cache.js +54 -0
  26. package/dist/chat/anthropic-planner.d.ts +98 -0
  27. package/dist/chat/anthropic-planner.js +1012 -0
  28. package/dist/chat/changelog-coverage-validator.d.ts +37 -0
  29. package/dist/chat/changelog-coverage-validator.js +215 -0
  30. package/dist/chat/chat-pipeline-context.d.ts +211 -0
  31. package/dist/chat/chat-pipeline-context.js +249 -0
  32. package/dist/chat/chat-pipeline-deterministic.d.ts +61 -0
  33. package/dist/chat/chat-pipeline-deterministic.js +407 -0
  34. package/dist/chat/chat-pipeline-image.d.ts +86 -0
  35. package/dist/chat/chat-pipeline-image.js +897 -0
  36. package/dist/chat/chat-pipeline-shared.d.ts +69 -0
  37. package/dist/chat/chat-pipeline-shared.js +212 -0
  38. package/dist/chat/chat-pipeline-translation.d.ts +27 -0
  39. package/dist/chat/chat-pipeline-translation.js +417 -0
  40. package/dist/chat/chat-pipeline-ui.d.ts +14 -0
  41. package/dist/chat/chat-pipeline-ui.js +244 -0
  42. package/dist/chat/chat-pipeline.d.ts +99 -0
  43. package/dist/chat/chat-pipeline.js +3999 -0
  44. package/dist/chat/decomposer.d.ts +21 -0
  45. package/dist/chat/decomposer.js +65 -0
  46. package/dist/chat/gemini-planner.d.ts +70 -0
  47. package/dist/chat/gemini-planner.js +541 -0
  48. package/dist/chat/hallucination-validator.d.ts +36 -0
  49. package/dist/chat/hallucination-validator.js +110 -0
  50. package/dist/chat/locale-strings.d.ts +47 -0
  51. package/dist/chat/locale-strings.js +100 -0
  52. package/dist/chat/plan-json-schema.d.ts +133 -0
  53. package/dist/chat/plan-json-schema.js +112 -0
  54. package/dist/chat/planner-types.d.ts +120 -0
  55. package/dist/chat/planner-types.js +66 -0
  56. package/dist/chat/planner.d.ts +148 -0
  57. package/dist/chat/planner.js +1361 -0
  58. package/dist/chat/prompts.d.ts +67 -0
  59. package/dist/chat/prompts.js +356 -0
  60. package/dist/chat/provider-routing.d.ts +14 -0
  61. package/dist/chat/provider-routing.js +27 -0
  62. package/dist/chat/variation-pipeline.d.ts +135 -0
  63. package/dist/chat/variation-pipeline.js +837 -0
  64. package/dist/chat/vision-alt-generator.d.ts +35 -0
  65. package/dist/chat/vision-alt-generator.js +152 -0
  66. package/dist/cms/adapter.d.ts +62 -0
  67. package/dist/cms/adapter.js +1 -0
  68. package/dist/cms/bootstrap.d.ts +17 -0
  69. package/dist/cms/bootstrap.js +85 -0
  70. package/dist/cms/editor-api-adapter.d.ts +23 -0
  71. package/dist/cms/editor-api-adapter.js +71 -0
  72. package/dist/cms/index.d.ts +4 -0
  73. package/dist/cms/index.js +3 -0
  74. package/dist/cms/json-file-adapter.d.ts +11 -0
  75. package/dist/cms/json-file-adapter.js +62 -0
  76. package/dist/demo-mode.d.ts +59 -0
  77. package/dist/demo-mode.js +201 -0
  78. package/dist/errors.d.ts +67 -0
  79. package/dist/errors.js +129 -0
  80. package/dist/http/chat-stream-resumable.d.ts +108 -0
  81. package/dist/http/chat-stream-resumable.js +290 -0
  82. package/dist/http/chat-stream.d.ts +99 -0
  83. package/dist/http/chat-stream.js +92 -0
  84. package/dist/image/gdrive-client.d.ts +22 -0
  85. package/dist/image/gdrive-client.js +215 -0
  86. package/dist/image/image-helpers.d.ts +95 -0
  87. package/dist/image/image-helpers.js +488 -0
  88. package/dist/index.d.ts +1 -0
  89. package/dist/index.js +1 -0
  90. package/dist/jira/jira-approval.d.ts +22 -0
  91. package/dist/jira/jira-approval.js +51 -0
  92. package/dist/jira/jira-client.d.ts +44 -0
  93. package/dist/jira/jira-client.js +313 -0
  94. package/dist/jira/jira-poller.d.ts +46 -0
  95. package/dist/jira/jira-poller.js +184 -0
  96. package/dist/jira/jira-processor.d.ts +103 -0
  97. package/dist/jira/jira-processor.js +1085 -0
  98. package/dist/jira/jira-types.d.ts +117 -0
  99. package/dist/jira/jira-types.js +38 -0
  100. package/dist/logger.d.ts +12 -0
  101. package/dist/logger.js +28 -0
  102. package/dist/migration/mcp-server-stdio.d.ts +8 -0
  103. package/dist/migration/mcp-server-stdio.js +672 -0
  104. package/dist/migration/migration-prompt.d.ts +7 -0
  105. package/dist/migration/migration-prompt.js +197 -0
  106. package/dist/migration/migration-tools.d.ts +17 -0
  107. package/dist/migration/migration-tools.js +159 -0
  108. package/dist/migration/scrape-cache.d.ts +9 -0
  109. package/dist/migration/scrape-cache.js +19 -0
  110. package/dist/nlp/deterministic-planner-context.d.ts +141 -0
  111. package/dist/nlp/deterministic-planner-context.js +362 -0
  112. package/dist/nlp/deterministic-planner-pages.d.ts +26 -0
  113. package/dist/nlp/deterministic-planner-pages.js +170 -0
  114. package/dist/nlp/deterministic-planner-patches.d.ts +80 -0
  115. package/dist/nlp/deterministic-planner-patches.js +508 -0
  116. package/dist/nlp/deterministic-planner-refs.d.ts +33 -0
  117. package/dist/nlp/deterministic-planner-refs.js +164 -0
  118. package/dist/nlp/deterministic-planner-suggestions.d.ts +49 -0
  119. package/dist/nlp/deterministic-planner-suggestions.js +579 -0
  120. package/dist/nlp/deterministic-planner.d.ts +85 -0
  121. package/dist/nlp/deterministic-planner.js +1631 -0
  122. package/dist/nlp/intent-detection.d.ts +309 -0
  123. package/dist/nlp/intent-detection.js +730 -0
  124. package/dist/nlp/intent-helpers.d.ts +15 -0
  125. package/dist/nlp/intent-helpers.js +243 -0
  126. package/dist/nlp/intent-patterns.d.ts +40 -0
  127. package/dist/nlp/intent-patterns.js +223 -0
  128. package/dist/nlp/plan-normalizer.d.ts +41 -0
  129. package/dist/nlp/plan-normalizer.js +1537 -0
  130. package/dist/ops/destructive-action-gate.d.ts +44 -0
  131. package/dist/ops/destructive-action-gate.js +90 -0
  132. package/dist/ops/ops-engine.d.ts +151 -0
  133. package/dist/ops/ops-engine.js +1394 -0
  134. package/dist/publish/diff-engine.d.ts +18 -0
  135. package/dist/publish/diff-engine.js +305 -0
  136. package/dist/publish/publish-helpers.d.ts +87 -0
  137. package/dist/publish/publish-helpers.js +521 -0
  138. package/dist/publish/publish-target-registry.d.ts +7 -0
  139. package/dist/publish/publish-target-registry.js +61 -0
  140. package/dist/publish/publish-target.d.ts +81 -0
  141. package/dist/publish/publish-target.js +1 -0
  142. package/dist/publish/targets/deploy-hook.d.ts +13 -0
  143. package/dist/publish/targets/deploy-hook.js +123 -0
  144. package/dist/publish/targets/git.d.ts +13 -0
  145. package/dist/publish/targets/git.js +55 -0
  146. package/dist/publish/targets/site-contract.d.ts +19 -0
  147. package/dist/publish/targets/site-contract.js +124 -0
  148. package/dist/state/content-source.d.ts +17 -0
  149. package/dist/state/content-source.js +1 -0
  150. package/dist/state/in-memory-content-source.d.ts +27 -0
  151. package/dist/state/in-memory-content-source.js +51 -0
  152. package/dist/state/session-lock.d.ts +13 -0
  153. package/dist/state/session-lock.js +29 -0
  154. package/dist/state/session-state.d.ts +310 -0
  155. package/dist/state/session-state.js +1083 -0
  156. package/dist/state/sqlite-store-singleton.d.ts +31 -0
  157. package/dist/state/sqlite-store-singleton.js +170 -0
  158. package/dist/state/sqlite-store.d.ts +135 -0
  159. package/dist/state/sqlite-store.js +421 -0
  160. package/dist/telemetry/chat-telemetry.d.ts +105 -0
  161. package/dist/telemetry/chat-telemetry.js +247 -0
  162. package/dist/telemetry/eval-candidate-store.d.ts +50 -0
  163. package/dist/telemetry/eval-candidate-store.js +120 -0
  164. package/dist/telemetry/feedback-store.d.ts +34 -0
  165. package/dist/telemetry/feedback-store.js +76 -0
  166. package/dist/telemetry/jira-telemetry.d.ts +57 -0
  167. package/dist/telemetry/jira-telemetry.js +68 -0
  168. package/dist/telemetry/migration-telemetry.d.ts +35 -0
  169. package/dist/telemetry/migration-telemetry.js +40 -0
  170. package/dist/telemetry/usage.d.ts +24 -0
  171. package/dist/telemetry/usage.js +80 -0
  172. package/dist/tools/builtin-registrations.d.ts +12 -0
  173. package/dist/tools/builtin-registrations.js +33 -0
  174. package/dist/tools/builtins/gdrive-browse.d.ts +3 -0
  175. package/dist/tools/builtins/gdrive-browse.js +68 -0
  176. package/dist/tools/builtins/image-generate.d.ts +3 -0
  177. package/dist/tools/builtins/image-generate.js +211 -0
  178. package/dist/tools/builtins/unsplash-get-by-id.d.ts +23 -0
  179. package/dist/tools/builtins/unsplash-get-by-id.js +119 -0
  180. package/dist/tools/builtins/unsplash-search.d.ts +3 -0
  181. package/dist/tools/builtins/unsplash-search.js +74 -0
  182. package/dist/tools/executor.d.ts +23 -0
  183. package/dist/tools/executor.js +169 -0
  184. package/dist/tools/index.d.ts +5 -0
  185. package/dist/tools/index.js +5 -0
  186. package/dist/tools/registry.d.ts +21 -0
  187. package/dist/tools/registry.js +75 -0
  188. package/dist/tools/runtime.d.ts +27 -0
  189. package/dist/tools/runtime.js +48 -0
  190. package/dist/tools/schema-validator.d.ts +24 -0
  191. package/dist/tools/schema-validator.js +88 -0
  192. package/dist/tools/types.d.ts +86 -0
  193. package/dist/tools/types.js +1 -0
  194. package/dist/variation-images.d.ts +19 -0
  195. package/dist/variation-images.js +12 -0
  196. package/package.json +78 -0
@@ -0,0 +1,44 @@
1
+ import type { EditPlan, PageDoc } from "@avocadostudio-ai/shared";
2
+ /**
3
+ * Tier 1 destructive-action gate. Evaluates an edit plan and decides whether
4
+ * it should be held for explicit human approval before applying, regardless
5
+ * of undo/redo availability.
6
+ *
7
+ * Undo protects against recovery; it does not protect against:
8
+ * - AI misinterpretation (LLM deleted the wrong block)
9
+ * - Cross-page ops (undo is per-page, not atomic across pages)
10
+ * - Cognitive slip (user didn't notice until redo stack was cleared)
11
+ * - Server restart wiping the in-memory undo stack
12
+ *
13
+ * Tier 1 triggers (no toggle — always required):
14
+ * 1. remove_page (always — even empty pages represent structural site content)
15
+ * 2. Multi-page AI plans (ops touch more than one slug)
16
+ * 3. Bulk delete: >= BULK_REMOVE_BLOCK_THRESHOLD remove_block ops in a
17
+ * single plan, OR a plan that removes > HALF of the blocks on any page
18
+ */
19
+ export type DestructiveReason = {
20
+ kind: "remove_page";
21
+ slug: string;
22
+ blockCount: number;
23
+ } | {
24
+ kind: "multi_page_plan";
25
+ slugs: string[];
26
+ } | {
27
+ kind: "bulk_remove_blocks";
28
+ totalRemoveOps: number;
29
+ } | {
30
+ kind: "majority_page_wipe";
31
+ slug: string;
32
+ removing: number;
33
+ total: number;
34
+ };
35
+ export type DestructiveEvaluation = {
36
+ requiresApproval: boolean;
37
+ reasons: DestructiveReason[];
38
+ messages: string[];
39
+ };
40
+ export declare const BULK_REMOVE_BLOCK_THRESHOLD = 3;
41
+ export declare const MAJORITY_WIPE_RATIO = 0.5;
42
+ export type PageLookup = (slug: string) => PageDoc | null;
43
+ export declare function evaluateDestructiveActions(plan: Pick<EditPlan, "ops">, getPage: PageLookup): DestructiveEvaluation;
44
+ export declare function describeDestructiveReason(reason: DestructiveReason): string;
@@ -0,0 +1,90 @@
1
+ export const BULK_REMOVE_BLOCK_THRESHOLD = 3;
2
+ export const MAJORITY_WIPE_RATIO = 0.5;
3
+ function slugsTouchedByOps(ops) {
4
+ const set = new Set();
5
+ for (const op of ops) {
6
+ if (op.op === "create_page") {
7
+ set.add(op.page.slug);
8
+ continue;
9
+ }
10
+ if (op.op === "update_site_config")
11
+ continue;
12
+ // duplicate_page: pageSlug is the SOURCE (read-only); newPageSlug is the
13
+ // only page being modified. Skip the generic pageSlug add below so the
14
+ // source isn't counted as "touched" and a duplicate-and-modify plan
15
+ // doesn't trip the multi-page approval gate spuriously.
16
+ if (op.op === "duplicate_page") {
17
+ if (typeof op.newPageSlug === "string")
18
+ set.add(op.newPageSlug);
19
+ continue;
20
+ }
21
+ // duplicate_block to a different page: pageSlug is the SOURCE; toPageSlug
22
+ // is the only page being modified. Same rationale as duplicate_page.
23
+ if (op.op === "duplicate_block" && typeof op.toPageSlug === "string" && op.toPageSlug !== op.pageSlug) {
24
+ set.add(op.toPageSlug);
25
+ continue;
26
+ }
27
+ if ("pageSlug" in op && typeof op.pageSlug === "string")
28
+ set.add(op.pageSlug);
29
+ if (op.op === "duplicate_block" && typeof op.toPageSlug === "string")
30
+ set.add(op.toPageSlug);
31
+ if (op.op === "rename_page" && typeof op.newPageSlug === "string")
32
+ set.add(op.newPageSlug);
33
+ }
34
+ return Array.from(set);
35
+ }
36
+ export function evaluateDestructiveActions(plan, getPage) {
37
+ const reasons = [];
38
+ const ops = plan.ops;
39
+ // 1. remove_page — always destructive regardless of block count
40
+ for (const op of ops) {
41
+ if (op.op !== "remove_page")
42
+ continue;
43
+ const page = getPage(op.pageSlug);
44
+ const blockCount = page?.blocks?.length ?? 0;
45
+ reasons.push({ kind: "remove_page", slug: op.pageSlug, blockCount });
46
+ }
47
+ // 2. Multi-page plan (>1 slug touched in a single chat turn)
48
+ const touchedSlugs = slugsTouchedByOps(ops);
49
+ if (touchedSlugs.length > 1) {
50
+ reasons.push({ kind: "multi_page_plan", slugs: touchedSlugs });
51
+ }
52
+ // 3a. Bulk remove_block — absolute count across the whole plan
53
+ const removeBlockOps = ops.filter((op) => op.op === "remove_block");
54
+ if (removeBlockOps.length >= BULK_REMOVE_BLOCK_THRESHOLD) {
55
+ reasons.push({ kind: "bulk_remove_blocks", totalRemoveOps: removeBlockOps.length });
56
+ }
57
+ // 3b. Majority-wipe — plan removes > 50% of blocks on any single page
58
+ const removesBySlug = new Map();
59
+ for (const op of removeBlockOps) {
60
+ if (op.op !== "remove_block")
61
+ continue;
62
+ removesBySlug.set(op.pageSlug, (removesBySlug.get(op.pageSlug) ?? 0) + 1);
63
+ }
64
+ for (const [slug, removing] of removesBySlug) {
65
+ const page = getPage(slug);
66
+ const total = page?.blocks?.length ?? 0;
67
+ if (total > 0 && removing / total > MAJORITY_WIPE_RATIO) {
68
+ // Avoid duplicating with bulk_remove_blocks when both apply — both are
69
+ // informative, so we keep them.
70
+ reasons.push({ kind: "majority_page_wipe", slug, removing, total });
71
+ }
72
+ }
73
+ return {
74
+ requiresApproval: reasons.length > 0,
75
+ reasons,
76
+ messages: reasons.map(describeDestructiveReason)
77
+ };
78
+ }
79
+ export function describeDestructiveReason(reason) {
80
+ switch (reason.kind) {
81
+ case "remove_page":
82
+ return `You can still undo this later if you change your mind.`;
83
+ case "multi_page_plan":
84
+ return `This will apply changes across ${reason.slugs.length} pages at once (${reason.slugs.join(", ")}).`;
85
+ case "bulk_remove_blocks":
86
+ return `This will remove ${reason.totalRemoveOps} blocks at once.`;
87
+ case "majority_page_wipe":
88
+ return `This will remove most of the content on ${reason.slug} (${reason.removing} of ${reason.total} blocks).`;
89
+ }
90
+ }
@@ -0,0 +1,151 @@
1
+ import { type BlockManifest, type Operation } from "@avocadostudio-ai/shared";
2
+ import { type GuardrailErrorCategory, toErrorDetail as _unifiedToErrorDetail } from "../errors.ts";
3
+ import type { ContentSource } from "../state/content-source.ts";
4
+ import type { PublishDiff } from "@avocadostudio-ai/shared";
5
+ export declare const toErrorDetail: typeof _unifiedToErrorDetail;
6
+ export declare function isNoEffectiveChangeError(reason: string): boolean;
7
+ export declare function classifyGuardrailError(reason: string): GuardrailErrorCategory;
8
+ export declare function formatValidationError(reason: string): string;
9
+ export declare function isDeterministicRepairEligible(reason: string): boolean;
10
+ /**
11
+ * Extracts structured fields from a planner schema_violation reason so the
12
+ * repair prompt can tell the LLM exactly which path to fix and what kind of
13
+ * violation it was. The reason format produced by planner.ts is:
14
+ * `<zodMessage> at <path>. Parsed sample: <truncated json>`
15
+ *
16
+ * Falls back gracefully when fields are missing (e.g. non-zod failures that
17
+ * still classify as schema_violation via the keyword matcher).
18
+ */
19
+ export declare function parseSchemaViolationReason(reason: string): {
20
+ path: string | null;
21
+ zodMessage: string;
22
+ kind: "unknown_key" | "missing_required" | "type_mismatch" | "invalid_enum" | "invalid_discriminator" | "out_of_range" | "string_constraint" | "unknown";
23
+ };
24
+ export declare function buildDeterministicRepairFeedback(reason: string): string;
25
+ export type SkippedOperation = {
26
+ index: number;
27
+ op: Operation["op"];
28
+ reason: "empty_patch" | "unchanged_value";
29
+ pageSlug?: string;
30
+ blockId?: string;
31
+ };
32
+ export type FuzzyMatch = {
33
+ requestedId: string;
34
+ resolvedId: string;
35
+ resolvedIndex: number;
36
+ strategy: "strip_copy_suffix" | "append_copy_suffix" | "type_prefix";
37
+ };
38
+ /**
39
+ * Per-op outcome, collected for every op in the plan. `applied` and `skipped`
40
+ * mirror the existing all-or-nothing behaviour; `failed` only ever appears under
41
+ * `dryRun`, where a failing op is reported instead of aborting the whole plan so
42
+ * a preview can show "3 of 4 changes will apply".
43
+ */
44
+ export type OpResult = {
45
+ index: number;
46
+ op: Operation["op"];
47
+ status: "applied" | "skipped" | "failed";
48
+ reason?: string;
49
+ category?: string;
50
+ };
51
+ export type ApplyOpsOptions = {
52
+ componentsManifest?: BlockManifest;
53
+ contentSource?: ContentSource;
54
+ /**
55
+ * Validate-only: run every op against a clone, collect per-op results and a
56
+ * before→after diff, but never commit. Hard failures become `failed` op
57
+ * results (the plan does not abort), and each op is snapshot-isolated so a
58
+ * failure leaves no partial mutation that would corrupt the preview.
59
+ */
60
+ dryRun?: boolean;
61
+ /**
62
+ * Return a wholly-ineffective batch as `{ appliedCount: 0, skippedOps }` instead
63
+ * of throwing `no_effective_change`. Used by per-op streamed/progressive apply:
64
+ * applying ONE op at a time means an already-correct block (e.g. a section that's
65
+ * already in the target translation language) is a benign skip, not a plan-level
66
+ * failure. Without this, the first such op throws, the whole multi-op plan rolls
67
+ * back, and genuinely-changed blocks are discarded too.
68
+ */
69
+ allowNoEffectiveChange?: boolean;
70
+ };
71
+ export declare function isStructuralOperation(op: Operation): op is {
72
+ op: "add_block";
73
+ pageSlug: string;
74
+ block: {
75
+ id: string;
76
+ props: Record<string, unknown>;
77
+ type: string;
78
+ };
79
+ afterBlockId?: string | undefined;
80
+ } | {
81
+ op: "remove_block";
82
+ pageSlug: string;
83
+ blockId: string;
84
+ } | {
85
+ op: "move_block";
86
+ pageSlug: string;
87
+ blockId: string;
88
+ afterBlockId?: string | undefined;
89
+ } | {
90
+ op: "duplicate_block";
91
+ pageSlug: string;
92
+ blockId: string;
93
+ toPageSlug?: string | undefined;
94
+ newBlockId?: string | undefined;
95
+ afterBlockId?: string | undefined;
96
+ } | {
97
+ op: "add_item";
98
+ pageSlug: string;
99
+ blockId: string;
100
+ listKey: string;
101
+ item: Record<string, unknown>;
102
+ afterItemId?: string | undefined;
103
+ afterIndex?: number | undefined;
104
+ } | {
105
+ op: "remove_item";
106
+ pageSlug: string;
107
+ blockId: string;
108
+ listKey: string;
109
+ itemId?: string | undefined;
110
+ index?: number | undefined;
111
+ } | {
112
+ op: "move_item";
113
+ pageSlug: string;
114
+ blockId: string;
115
+ listKey: string;
116
+ itemId?: string | undefined;
117
+ index?: number | undefined;
118
+ afterItemId?: string | undefined;
119
+ afterIndex?: number | undefined;
120
+ };
121
+ /**
122
+ * Validate an array of operations against the canonical Zod schema.
123
+ * Returns the parsed (typed) operations or throws an `OperationError`
124
+ * with category `schema_violation`.
125
+ */
126
+ export declare function validateOperations(ops: unknown[]): Operation[];
127
+ export declare function applyOpsAtomically(session: string, ops: Operation[], options?: ApplyOpsOptions): Promise<{
128
+ appliedCount: number;
129
+ skippedOps: SkippedOperation[];
130
+ fuzzyMatches: FuzzyMatch[];
131
+ duplicatedPages: {
132
+ slug: string;
133
+ blockIdMap: Record<string, string>;
134
+ }[];
135
+ opResults: OpResult[];
136
+ preview: PublishDiff;
137
+ dryRun: true;
138
+ } | {
139
+ appliedCount: number;
140
+ skippedOps: SkippedOperation[];
141
+ fuzzyMatches: FuzzyMatch[];
142
+ duplicatedPages: {
143
+ slug: string;
144
+ blockIdMap: Record<string, string>;
145
+ }[];
146
+ opResults: OpResult[];
147
+ preview: PublishDiff | undefined;
148
+ dryRun: false;
149
+ }>;
150
+ export declare function pickFocusBlockId(ops: Operation[]): string | undefined;
151
+ export declare function pickUpdatedSlug(session: string, currentSlug: string, ops: Operation[]): string | undefined;