@beyondwork/docx-react-component 1.0.124 → 1.0.126

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 (101) hide show
  1. package/dist/api/public-types.cjs +147 -35
  2. package/dist/api/public-types.d.cts +2 -2
  3. package/dist/api/public-types.d.ts +2 -2
  4. package/dist/api/public-types.js +3 -3
  5. package/dist/api/v3.cjs +796 -102
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +10 -10
  9. package/dist/{canonical-document-CG2TgAzj.d.cts → canonical-document-CXCFCbAz.d.cts} +2 -0
  10. package/dist/{canonical-document-CG2TgAzj.d.ts → canonical-document-CXCFCbAz.d.ts} +2 -0
  11. package/dist/{chunk-PFYUJU3Q.js → chunk-2QL5DAKF.js} +98 -43
  12. package/dist/{chunk-4IPEZYQX.js → chunk-4EENH4FG.js} +1 -1
  13. package/dist/{chunk-BOHHIVQ2.js → chunk-4G3OS2H6.js} +3 -3
  14. package/dist/{chunk-A74Y5NE4.js → chunk-4YJVRIUB.js} +52 -21
  15. package/dist/{chunk-FNWKE74J.js → chunk-5DGKFNQT.js} +5 -1
  16. package/dist/{chunk-RSYN6FTS.js → chunk-6F5QW44A.js} +2 -2
  17. package/dist/{chunk-ZMRO6P3A.js → chunk-6IGWPAR4.js} +505 -44
  18. package/dist/{chunk-KOHQFZMM.js → chunk-BYSRJ4FE.js} +1 -1
  19. package/dist/{chunk-H6IL5ABU.js → chunk-CXSYRB37.js} +64 -20
  20. package/dist/{chunk-32ZAOQ54.js → chunk-D5HYZQTG.js} +1 -1
  21. package/dist/{chunk-TY4DIJO3.js → chunk-ESJ2MES5.js} +1 -1
  22. package/dist/{chunk-Q76XPPTA.js → chunk-FPRWV54X.js} +101 -14
  23. package/dist/{chunk-MPH4ZQS4.js → chunk-GL7XRYBY.js} +624 -87
  24. package/dist/{chunk-IR7QV2BX.js → chunk-KV435YXO.js} +2 -2
  25. package/dist/{chunk-N4VIXI2Z.js → chunk-MWSBGJQO.js} +137 -18
  26. package/dist/{chunk-7PC6XUNO.js → chunk-TQDQU2E3.js} +2 -2
  27. package/dist/{chunk-4B74ETJI.js → chunk-V6XVZFFH.js} +2 -2
  28. package/dist/{chunk-NAMAWCXN.js → chunk-YD2JE54B.js} +1 -1
  29. package/dist/{chunk-ZRHLLPSJ.js → chunk-YHZHPXDB.js} +85 -18
  30. package/dist/{chunk-HXHQA4BU.js → chunk-YIYM4ZAP.js} +1 -1
  31. package/dist/{chunk-LGWNN3L2.js → chunk-ZDOAUP3V.js} +2 -2
  32. package/dist/compare.d.cts +1 -1
  33. package/dist/compare.d.ts +1 -1
  34. package/dist/core/commands/formatting-commands.d.cts +2 -2
  35. package/dist/core/commands/formatting-commands.d.ts +2 -2
  36. package/dist/core/commands/image-commands.cjs +65 -20
  37. package/dist/core/commands/image-commands.d.cts +2 -2
  38. package/dist/core/commands/image-commands.d.ts +2 -2
  39. package/dist/core/commands/image-commands.js +5 -5
  40. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  41. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  42. package/dist/core/commands/style-commands.d.cts +2 -2
  43. package/dist/core/commands/style-commands.d.ts +2 -2
  44. package/dist/core/commands/table-structure-commands.cjs +65 -20
  45. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  46. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  47. package/dist/core/commands/table-structure-commands.js +4 -4
  48. package/dist/core/commands/text-commands.cjs +66 -21
  49. package/dist/core/commands/text-commands.d.cts +2 -2
  50. package/dist/core/commands/text-commands.d.ts +2 -2
  51. package/dist/core/commands/text-commands.js +5 -5
  52. package/dist/core/selection/mapping.d.cts +2 -2
  53. package/dist/core/selection/mapping.d.ts +2 -2
  54. package/dist/core/state/editor-state.d.cts +2 -2
  55. package/dist/core/state/editor-state.d.ts +2 -2
  56. package/dist/index.cjs +1677 -240
  57. package/dist/index.d.cts +5 -5
  58. package/dist/index.d.ts +5 -5
  59. package/dist/index.js +62 -25
  60. package/dist/io/docx-session.cjs +51 -20
  61. package/dist/io/docx-session.d.cts +4 -4
  62. package/dist/io/docx-session.d.ts +4 -4
  63. package/dist/io/docx-session.js +4 -4
  64. package/dist/legal.cjs +36 -12
  65. package/dist/legal.d.cts +1 -1
  66. package/dist/legal.d.ts +1 -1
  67. package/dist/legal.js +3 -3
  68. package/dist/{loader-D9y4ZRjj.d.ts → loader-CS9-9KFa.d.ts} +3 -3
  69. package/dist/{loader-D9KCtj4m.d.cts → loader-OoWJ1_17.d.cts} +3 -3
  70. package/dist/{public-types-CNnMHZM9.d.ts → public-types-BP3vqJR5.d.cts} +157 -11
  71. package/dist/{public-types-DajNGKV4.d.cts → public-types-DdcHqcow.d.ts} +157 -11
  72. package/dist/public-types.cjs +147 -35
  73. package/dist/public-types.d.cts +2 -2
  74. package/dist/public-types.d.ts +2 -2
  75. package/dist/public-types.js +3 -3
  76. package/dist/runtime/collab.d.cts +3 -3
  77. package/dist/runtime/collab.d.ts +3 -3
  78. package/dist/runtime/document-runtime.cjs +945 -134
  79. package/dist/runtime/document-runtime.d.cts +2 -2
  80. package/dist/runtime/document-runtime.d.ts +2 -2
  81. package/dist/runtime/document-runtime.js +14 -14
  82. package/dist/{session-DyQGlryH.d.cts → session-Cq-fzx3B.d.cts} +3 -3
  83. package/dist/{session-DEmaOEjA.d.ts → session-DyFQt8Ph.d.ts} +3 -3
  84. package/dist/session.cjs +51 -20
  85. package/dist/session.d.cts +5 -5
  86. package/dist/session.d.ts +5 -5
  87. package/dist/session.js +5 -5
  88. package/dist/tailwind.cjs +238 -73
  89. package/dist/tailwind.d.cts +2 -2
  90. package/dist/tailwind.d.ts +2 -2
  91. package/dist/tailwind.js +7 -7
  92. package/dist/{types-CxE1aZiv.d.cts → types-Bg7D-GD3.d.cts} +2 -2
  93. package/dist/{types-DjJNaE9c.d.ts → types-bJAgMq1M.d.ts} +2 -2
  94. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  95. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  96. package/dist/ui-tailwind/editor-surface/search-plugin.js +4 -4
  97. package/dist/ui-tailwind.cjs +238 -73
  98. package/dist/ui-tailwind.d.cts +3 -3
  99. package/dist/ui-tailwind.d.ts +3 -3
  100. package/dist/ui-tailwind.js +7 -7
  101. package/package.json +1 -1
@@ -17,7 +17,7 @@ import {
17
17
  resolveScopeRange,
18
18
  scopeSpecificity,
19
19
  searchDocument
20
- } from "./chunk-Q76XPPTA.js";
20
+ } from "./chunk-FPRWV54X.js";
21
21
  import {
22
22
  BROADCAST_COMMAND_TYPES,
23
23
  COMMAND_EVENT_SCHEMA_VERSION,
@@ -28,7 +28,7 @@ import {
28
28
  buildPageAnchorElementId,
29
29
  createUiApi,
30
30
  emitUxResponse
31
- } from "./chunk-HXHQA4BU.js";
31
+ } from "./chunk-YIYM4ZAP.js";
32
32
  import {
33
33
  DEFAULT_PX_PER_TWIP,
34
34
  DEFAULT_REGISTRY_ENTRIES,
@@ -36,23 +36,23 @@ import {
36
36
  LAYCACHE_SCHEMA_VERSION,
37
37
  LAYOUT_ENGINE_VERSION,
38
38
  createScopeTagRegistry
39
- } from "./chunk-ZRHLLPSJ.js";
39
+ } from "./chunk-YHZHPXDB.js";
40
40
  import {
41
41
  chartModelStore,
42
42
  createFormattingContext
43
- } from "./chunk-H6IL5ABU.js";
43
+ } from "./chunk-CXSYRB37.js";
44
44
  import {
45
45
  deriveDocumentStats
46
46
  } from "./chunk-OYGMRRR7.js";
47
47
  import {
48
48
  DocxSession
49
- } from "./chunk-7PC6XUNO.js";
49
+ } from "./chunk-TQDQU2E3.js";
50
50
  import {
51
51
  WORKFLOW_PAYLOAD_PART_PATH,
52
52
  buildEditorStateXml,
53
53
  parseEditorStateXml,
54
54
  parseWorkflowPayloadEnvelopeFromPackage
55
- } from "./chunk-4B74ETJI.js";
55
+ } from "./chunk-V6XVZFFH.js";
56
56
  import {
57
57
  EMU_PER_PX,
58
58
  GRADIENT_STOP_UNITS,
@@ -61,7 +61,7 @@ import {
61
61
  createHeaderFooterStoryKey,
62
62
  createNoteStoryKey,
63
63
  validateEditableTargetRef
64
- } from "./chunk-FNWKE74J.js";
64
+ } from "./chunk-5DGKFNQT.js";
65
65
  import {
66
66
  readOpcPackage
67
67
  } from "./chunk-OL2UEHRP.js";
@@ -6302,6 +6302,17 @@ var hyperlinkDestinationEditMetadata = actionMethodMetadata(
6302
6302
  expectedDelta: "hyperlink destination changes"
6303
6303
  }
6304
6304
  );
6305
+ var hyperlinkTextEditMetadata = actionMethodMetadata(
6306
+ "hyperlinkTextEdit",
6307
+ "mutate",
6308
+ "actions-link-bookmark",
6309
+ "Edit supported hyperlink display text through the L07 text-leaf command target; broad carrier scope rewrite remains refused.",
6310
+ {
6311
+ uiVisible: true,
6312
+ expectsUxResponse: "inline-change",
6313
+ expectedDelta: "hyperlink display text changes"
6314
+ }
6315
+ );
6305
6316
  var listOperationMetadata = actionMethodMetadata(
6306
6317
  "listOperation",
6307
6318
  "mutate",
@@ -6361,6 +6372,7 @@ var ACTION_METHODS = Object.freeze([
6361
6372
  "tocRefresh",
6362
6373
  "bookmarkEdit",
6363
6374
  "hyperlinkDestinationEdit",
6375
+ "hyperlinkTextEdit",
6364
6376
  "listOperation",
6365
6377
  "tableFragment",
6366
6378
  "tableSelection",
@@ -6370,6 +6382,9 @@ var DEFAULT_LOCATE_LIMIT = 20;
6370
6382
  var DEFAULT_REWRITE_ALL_LIMIT = 10;
6371
6383
  var DEFAULT_TABLE_TEXT_SCOPE_LIMIT = 3;
6372
6384
  var DEFAULT_PLAN_STEP_LIMIT = 20;
6385
+ function documentContentHash(runtime) {
6386
+ return JSON.stringify(runtime.getCanonicalDocument().content);
6387
+ }
6373
6388
  function createActionsFamily(runtime) {
6374
6389
  const category = {
6375
6390
  discover(input) {
@@ -6616,6 +6631,14 @@ function createActionsFamily(runtime) {
6616
6631
  ...readback ? { text: readback.text, excerpt: excerpt(readback.text) } : {}
6617
6632
  };
6618
6633
  }
6634
+ if (resolved.target.kind === "editable-text") {
6635
+ return {
6636
+ status: "read",
6637
+ target: summarizeTarget(resolved.target),
6638
+ text: resolved.target.readback.text,
6639
+ excerpt: excerpt(resolved.target.readback.text)
6640
+ };
6641
+ }
6619
6642
  const text = resolved.target.scope.content.text;
6620
6643
  return {
6621
6644
  status: "read",
@@ -6696,6 +6719,31 @@ function createActionsFamily(runtime) {
6696
6719
  input
6697
6720
  );
6698
6721
  },
6722
+ hyperlinkTextEdit(input) {
6723
+ if (input.text === void 0) {
6724
+ return blockedApply(
6725
+ "actions:hyperlink-text-edit:text-required",
6726
+ "input",
6727
+ "Hyperlink display text edit actions require a text value.",
6728
+ "Retry with a text string."
6729
+ );
6730
+ }
6731
+ const resolved = resolveTarget(runtime, input.target);
6732
+ if (!resolved.ok) return blockedApplyFromResolution(resolved);
6733
+ if (resolved.target.kind !== "editable-text" || resolved.target.targetKind !== "hyperlink-text") {
6734
+ return blockedApply(
6735
+ "actions:hyperlink-text-edit:hyperlink-text-handle-required",
6736
+ "unsupported",
6737
+ "Hyperlink display text edits require an exact hyperlink-text actionHandle.",
6738
+ "Call ai.actions.locateAll and retry with a returned scope-command:text-leaf actionHandle."
6739
+ );
6740
+ }
6741
+ return applyEditableTextRewrite(runtime, resolved.target, {
6742
+ text: input.text,
6743
+ actorId: input.actorId,
6744
+ origin: input.origin
6745
+ });
6746
+ },
6699
6747
  listOperation(input) {
6700
6748
  return applyListOperation(runtime, input);
6701
6749
  },
@@ -6744,6 +6792,7 @@ function runPlan(runtime, input) {
6744
6792
  for (const step of input.steps) {
6745
6793
  const result = runPlanStep(runtime, mode, step, input);
6746
6794
  results.push(result);
6795
+ if (isSuspectMutationStep(result)) break;
6747
6796
  if (stopOnBlocker && (result.status === "blocked" || result.status === "unsupported")) {
6748
6797
  break;
6749
6798
  }
@@ -6808,24 +6857,27 @@ function runPlanStep(runtime, mode, step, plan) {
6808
6857
  ...before.readback ? { beforeReadback: before.readback } : {}
6809
6858
  };
6810
6859
  }
6860
+ const documentHashBeforeApply = documentContentHash(runtime);
6811
6861
  const applied = applyPlanStep(runtime, step, plan);
6862
+ const documentHashAfterApply = documentContentHash(runtime);
6863
+ const projectedApply = !applied.applied && documentHashAfterApply !== documentHashBeforeApply ? withSuspectMutationApplyResult(applied, step.id, applied.target ?? before.target) : applied;
6812
6864
  const after = step.kind === "flag" ? before : step.target ? readPlanTarget(runtime, step.target) : before;
6813
6865
  return {
6814
6866
  id: step.id,
6815
6867
  kind: step.kind,
6816
- status: applied.status === "unsupported" ? "unsupported" : applied.applied ? "applied" : "blocked",
6817
- applied: applied.applied,
6818
- changed: applied.changed,
6819
- ...applied.target ?? before.target ? { target: applied.target ?? before.target } : {},
6868
+ status: projectedApply.status === "unsupported" ? "unsupported" : projectedApply.applied ? "applied" : "blocked",
6869
+ applied: projectedApply.applied,
6870
+ changed: projectedApply.changed,
6871
+ ...projectedApply.target ?? before.target ? { target: projectedApply.target ?? before.target } : {},
6820
6872
  ...before.tableAction ? { tableAction: before.tableAction } : {},
6821
6873
  ...before.readback ? { beforeReadback: before.readback } : {},
6822
6874
  ...after.ok && after.readback ? { afterReadback: after.readback } : {},
6823
- ...applied.proposalId ? { proposalId: applied.proposalId } : {},
6824
- ...applied.posture ? { posture: applied.posture } : {},
6825
- ...applied.blockers ? { blockers: applied.blockers } : {},
6826
- ...applied.blockerDetails ? { blockerDetails: applied.blockerDetails } : {},
6827
- ...applied.auditReference ? { auditReference: applied.auditReference } : {},
6828
- ...applied.commandReference ? { commandReference: applied.commandReference } : {}
6875
+ ...projectedApply.proposalId ? { proposalId: projectedApply.proposalId } : {},
6876
+ ...projectedApply.posture ? { posture: projectedApply.posture } : {},
6877
+ ...projectedApply.blockers ? { blockers: projectedApply.blockers } : {},
6878
+ ...projectedApply.blockerDetails ? { blockerDetails: projectedApply.blockerDetails } : {},
6879
+ ...projectedApply.auditReference ? { auditReference: projectedApply.auditReference } : {},
6880
+ ...projectedApply.commandReference ? { commandReference: projectedApply.commandReference } : {}
6829
6881
  };
6830
6882
  }
6831
6883
  function runPlanTableActionStep(runtime, mode, step, plan) {
@@ -6953,6 +7005,23 @@ function locateAll(runtime, input) {
6953
7005
  isEmpty: text.trim().length === 0
6954
7006
  });
6955
7007
  }
7008
+ if (matches.length < limit && !input.kind) {
7009
+ for (const scope of scopes) {
7010
+ if (matches.length >= limit) break;
7011
+ for (const action of editableTextActionsForScope(runtime, scope.handle)) {
7012
+ if (matches.length >= limit) break;
7013
+ if (!textMatches(action.readback.text, input.query, input.matchCase)) continue;
7014
+ matches.push({
7015
+ kind: action.targetKind,
7016
+ text: action.readback.text,
7017
+ excerpt: excerpt(action.readback.text),
7018
+ actionHandle: action.actionHandle,
7019
+ readback: action.readback,
7020
+ isEmpty: action.readback.isEmpty
7021
+ });
7022
+ }
7023
+ }
7024
+ }
6956
7025
  if (matches.length < limit && shouldScanTableText) {
6957
7026
  const tableTextScopeLimit = Math.max(
6958
7027
  0,
@@ -6987,23 +7056,27 @@ function locateAll(runtime, input) {
6987
7056
  function resolveTarget(runtime, target) {
6988
7057
  if ("actionHandle" in target) {
6989
7058
  const action = findTableAction(runtime, target.actionHandle);
6990
- if (!action) {
6991
- return blockedResolution(
6992
- `actions:target:action-handle-not-found:${target.actionHandle}`,
6993
- "unresolved-target",
6994
- "No current table text action matches the supplied actionHandle.",
6995
- "Call ai.actions.locateAll or ai.listTableActions again and retry with a fresh actionHandle."
6996
- );
7059
+ if (action) {
7060
+ if (action.family !== "table-text") {
7061
+ return blockedResolution(
7062
+ `actions:target:action-handle-not-text:${target.actionHandle}`,
7063
+ "unsupported",
7064
+ "This actionHandle is not a table text action.",
7065
+ "Use table structure handles with ai.applyTableAction, or use a table text actionHandle for rewrite."
7066
+ );
7067
+ }
7068
+ return { ok: true, target: { kind: "table-text", action } };
6997
7069
  }
6998
- if (action.family !== "table-text") {
6999
- return blockedResolution(
7000
- `actions:target:action-handle-not-text:${target.actionHandle}`,
7001
- "unsupported",
7002
- "This actionHandle is not a table text action.",
7003
- "Use table structure handles with ai.applyTableAction, or use a table text actionHandle for rewrite."
7004
- );
7070
+ const editableTextAction = findEditableTextAction(runtime, target.actionHandle);
7071
+ if (editableTextAction) {
7072
+ return { ok: true, target: editableTextAction };
7005
7073
  }
7006
- return { ok: true, target: { kind: "table-text", action } };
7074
+ return blockedResolution(
7075
+ `actions:target:action-handle-not-found:${target.actionHandle}`,
7076
+ "unresolved-target",
7077
+ "No current table text or editable text action matches the supplied actionHandle.",
7078
+ "Call ai.actions.locateAll again and retry with a fresh actionHandle."
7079
+ );
7007
7080
  }
7008
7081
  if ("handle" in target) {
7009
7082
  const compiled = createScopeCompilerService(runtime).compileScopeById(target.handle.scopeId);
@@ -7088,7 +7161,21 @@ function applyRewrite(runtime, target, input) {
7088
7161
  ...result2.afterReadback ? { afterReadback: result2.afterReadback } : {}
7089
7162
  };
7090
7163
  }
7164
+ if (target.kind === "editable-text") {
7165
+ return applyEditableTextRewrite(runtime, target, input);
7166
+ }
7167
+ const rewriteBlocker = scopeRewriteCapabilityBlocker(target.scope);
7168
+ if (rewriteBlocker) {
7169
+ return blockedApply(
7170
+ rewriteBlocker.code,
7171
+ rewriteBlocker.category,
7172
+ rewriteBlocker.message,
7173
+ rewriteBlocker.nextStep,
7174
+ [rewriteBlocker]
7175
+ );
7176
+ }
7091
7177
  const beforeText = target.scope.content.text;
7178
+ const documentHashBeforeApply = documentContentHash(runtime);
7092
7179
  const result = createReplacementFamily(runtime).applyReplacementScope({
7093
7180
  targetScopeId: target.handle.scopeId,
7094
7181
  operation: "replace",
@@ -7100,7 +7187,22 @@ function applyRewrite(runtime, target, input) {
7100
7187
  ...input.origin ? { origin: input.origin } : {},
7101
7188
  ...input.proposalId ? { proposalId: input.proposalId } : {}
7102
7189
  });
7103
- return projectRewriteScopeResult(runtime, result, target, beforeText, input.text);
7190
+ const documentMutated = documentContentHash(runtime) !== documentHashBeforeApply;
7191
+ if (!result.applied) {
7192
+ return documentMutated ? withSuspectMutationApplyResult(
7193
+ projectApplyResult(result, target),
7194
+ target.handle.scopeId,
7195
+ summarizeTarget(target)
7196
+ ) : projectApplyResult(result, target);
7197
+ }
7198
+ return projectRewriteScopeResult(
7199
+ runtime,
7200
+ result,
7201
+ target,
7202
+ beforeText,
7203
+ input.text,
7204
+ documentMutated
7205
+ );
7104
7206
  }
7105
7207
  function projectApplyResult(result, target) {
7106
7208
  return {
@@ -7121,7 +7223,79 @@ function projectApplyResult(result, target) {
7121
7223
  ...result.auditReference ? { auditReference: result.auditReference } : {}
7122
7224
  };
7123
7225
  }
7124
- function projectRewriteScopeResult(runtime, result, target, beforeText, proposedText) {
7226
+ function applyEditableTextRewrite(runtime, target, input) {
7227
+ const before = runtime.getCanonicalDocument();
7228
+ runtime.dispatch({
7229
+ type: "selection.set",
7230
+ selection: target.selection,
7231
+ origin: actionOrigin(runtime, input)
7232
+ });
7233
+ runtime.applyActiveStoryTextCommand({
7234
+ type: "text.insert",
7235
+ text: input.text,
7236
+ editableTarget: target.editableTarget,
7237
+ origin: actionOrigin(runtime, input)
7238
+ });
7239
+ const changed = runtime.getCanonicalDocument() !== before;
7240
+ if (!changed) {
7241
+ return blockedApply(
7242
+ `actions:editable-text:runtime-noop:${target.actionHandle}`,
7243
+ "blocked",
7244
+ "The editable text command was accepted but produced no document change.",
7245
+ "Refresh the action handle with ai.actions.locateAll and retry; route persistent failures to L07 text command support.",
7246
+ [
7247
+ blockerWithOwner(
7248
+ `actions:editable-text:runtime-noop:${target.actionHandle}`,
7249
+ "blocked",
7250
+ "The editable text command was accepted but produced no document change.",
7251
+ "Refresh the action handle with ai.actions.locateAll and retry; route persistent failures to L07 text command support.",
7252
+ "L07 runtime text command support"
7253
+ )
7254
+ ]
7255
+ );
7256
+ }
7257
+ const afterTarget = findEditableTextActionByTargetKey(
7258
+ runtime,
7259
+ target.editableTarget.targetKey
7260
+ );
7261
+ const afterReadback = afterTarget?.readback ?? editableTextTargetState(
7262
+ runtime.getCanonicalDocument(),
7263
+ target.editableTarget
7264
+ )?.readback;
7265
+ if (!afterReadback || afterReadback.text !== input.text) {
7266
+ return {
7267
+ status: "blocked",
7268
+ applied: false,
7269
+ changed: true,
7270
+ target: summarizeTarget(afterTarget ?? target),
7271
+ posture: "suspect-readback",
7272
+ blockers: Object.freeze([`actions:editable-text:readback-mismatch:${target.actionHandle}`]),
7273
+ blockerDetails: Object.freeze([
7274
+ blocker(
7275
+ `actions:editable-text:readback-mismatch:${target.actionHandle}`,
7276
+ "blocked",
7277
+ "The editable text command changed the document, but exact target readback did not match the proposed text.",
7278
+ "Treat the mutation as suspect. Re-read the target and export before claiming success."
7279
+ )
7280
+ ]),
7281
+ ...afterReadback ? { afterReadback } : {}
7282
+ };
7283
+ }
7284
+ return {
7285
+ status: "applied",
7286
+ applied: true,
7287
+ changed: true,
7288
+ target: summarizeTarget(afterTarget ?? { ...target, readback: afterReadback }),
7289
+ commandReference: {
7290
+ command: "text.insert",
7291
+ actorId: input.actorId ?? "v3-ai-api",
7292
+ origin: input.origin ?? "agent",
7293
+ emittedAtUtc: currentAuditTimestamp(runtime)
7294
+ },
7295
+ afterReadback
7296
+ };
7297
+ }
7298
+ function projectRewriteScopeResult(runtime, result, target, beforeText, proposedText, documentMutated) {
7125
7299
  if (!result.applied) return projectApplyResult(result, target);
7126
7300
  const compiledAfter = createScopeCompilerService(runtime).compileScopeById(
7127
7301
  target.handle.scopeId
@@ -7132,7 +7306,8 @@ function projectRewriteScopeResult(runtime, result, target, beforeText, proposed
7132
7306
  target,
7133
7307
  `actions:rewrite:authoritative-readback-unresolvable:${target.handle.scopeId}`,
7134
7308
  "The replacement primitive reported success, but the target scope could not be re-read afterwards.",
7135
- "Treat the mutation as untrusted. Re-locate the target and retry only after the scope resolves, or create an issue flag instead."
7309
+ "Treat the mutation as untrusted. Re-locate the target and retry only after the scope resolves, or create an issue flag instead.",
7310
+ documentMutated
7136
7311
  );
7137
7312
  }
7138
7313
  const afterText = compiledAfter.scope.content.text;
@@ -7144,7 +7319,8 @@ function projectRewriteScopeResult(runtime, result, target, beforeText, proposed
7144
7319
  { ...target, scope: compiledAfter.scope, handle: compiledAfter.scope.handle },
7145
7320
  `actions:rewrite:authoritative-readback-unchanged:${target.handle.scopeId}`,
7146
7321
  "The replacement primitive reported success, but authoritative scope readback showed unchanged text.",
7147
- "Treat the mutation as not applied. Retry with a narrower scope or create an issue flag; do not claim the replacement succeeded."
7322
+ "Treat the mutation as not applied. Retry with a narrower scope or create an issue flag; do not claim the replacement succeeded.",
7323
+ documentMutated
7148
7324
  );
7149
7325
  }
7150
7326
  if (!expectedPresent) {
@@ -7153,7 +7329,8 @@ function projectRewriteScopeResult(runtime, result, target, beforeText, proposed
7153
7329
  { ...target, scope: compiledAfter.scope, handle: compiledAfter.scope.handle },
7154
7330
  `actions:rewrite:authoritative-readback-mismatch:${target.handle.scopeId}`,
7155
7331
  "The replacement primitive reported success, but authoritative scope readback did not contain the proposed text.",
7156
- "Treat the mutation as suspect. Re-read the target, inspect the exported package when available, and retry only with a verified target."
7332
+ "Treat the mutation as suspect. Re-read the target, inspect the exported package when available, and retry only with a verified target.",
7333
+ documentMutated
7157
7334
  );
7158
7335
  }
7159
7336
  return {
@@ -7170,17 +7347,27 @@ function projectRewriteScopeResult(runtime, result, target, beforeText, proposed
7170
7347
  ...result.auditReference ? { auditReference: result.auditReference } : {}
7171
7348
  };
7172
7349
  }
7173
- function blockedRewriteReadback(result, target, code, message, nextStep) {
7350
+ function blockedRewriteReadback(result, target, code, message, nextStep, documentMutated = false) {
7174
7351
  const detail = blocker(code, "blocked", message, nextStep);
7352
+ const details = documentMutated ? [
7353
+ detail,
7354
+ blockerWithOwner(
7355
+ `actions:rewrite:suspect-mutation:${target.handle.scopeId}`,
7356
+ "blocked",
7357
+ "The document changed even though authoritative target readback failed.",
7358
+ "Abort the plan, inspect the export/readback evidence, and route the target to L08/L07 scope edit-target mapping before retrying.",
7359
+ "L08 semantic scopes and L07 runtime text commands"
7360
+ )
7361
+ ] : [detail];
7175
7362
  return {
7176
7363
  status: "blocked",
7177
7364
  applied: false,
7178
- changed: false,
7365
+ changed: documentMutated,
7179
7366
  target: summarizeTarget(target),
7180
7367
  proposalId: result.proposalId,
7181
- posture: "suspect-readback",
7182
- blockers: Object.freeze([detail.code]),
7183
- blockerDetails: Object.freeze([detail]),
7368
+ posture: documentMutated ? "suspect-mutation" : "suspect-readback",
7369
+ blockers: Object.freeze(details.map((entry) => entry.code)),
7370
+ blockerDetails: Object.freeze(details),
7184
7371
  ...result.auditReference ? { auditReference: result.auditReference } : {}
7185
7372
  };
7186
7373
  }
@@ -7196,11 +7383,23 @@ function summarizeTarget(target) {
7196
7383
  canMark: false
7197
7384
  };
7198
7385
  }
7386
+ if (target.kind === "editable-text") {
7387
+ return {
7388
+ kind: target.targetKind,
7389
+ handle: target.ownerHandle,
7390
+ actionHandle: target.actionHandle,
7391
+ readback: target.readback,
7392
+ canRewriteText: true,
7393
+ canInsertAdjacentText: false,
7394
+ canFlag: false,
7395
+ canMark: false
7396
+ };
7397
+ }
7199
7398
  return {
7200
7399
  kind: target.scope.kind,
7201
7400
  handle: target.handle,
7202
7401
  canRewriteText: canRewriteScopeText(target.scope),
7203
- canInsertAdjacentText: canRewriteScopeText(target.scope),
7402
+ canInsertAdjacentText: canInsertAdjacentScopeText(target.scope),
7204
7403
  canFlag: true,
7205
7404
  canMark: canMarkScope(target.scope)
7206
7405
  };
@@ -7212,6 +7411,34 @@ function tableTextActionsForScope(runtime, handle) {
7212
7411
  });
7213
7412
  return result.actions.filter((action) => action.family === "table-text");
7214
7413
  }
7414
+ function editableTextActionsForScope(runtime, handle) {
7415
+ const bundle = createScopeCompilerService(runtime).compileBundleById(
7416
+ handle.scopeId,
7417
+ currentAuditTimestamp(runtime)
7418
+ );
7419
+ const entries = bundle?.evidence.editableTargets?.entries ?? [];
7420
+ const currentTargets = collectEditableTargetRefs(runtime.getCanonicalDocument());
7421
+ const actions = [];
7422
+ for (const entry of entries) {
7423
+ if (entry.kind !== "hyperlink-text" || entry.commandFamily !== "text-leaf" || entry.runtimeCommand.status !== "supported" || !entry.runtimeCommand.actionHandle) {
7424
+ continue;
7425
+ }
7426
+ const currentTarget = currentTargets.find((target) => target.targetKey === entry.targetKey);
7427
+ if (!currentTarget || currentTarget.kind !== "hyperlink-text") continue;
7428
+ const targetState = editableTextTargetState(runtime.getCanonicalDocument(), currentTarget);
7429
+ if (!targetState) continue;
7430
+ actions.push({
7431
+ kind: "editable-text",
7432
+ targetKind: "hyperlink-text",
7433
+ actionHandle: entry.runtimeCommand.actionHandle,
7434
+ editableTarget: currentTarget,
7435
+ ownerHandle: handle,
7436
+ readback: targetState.readback,
7437
+ selection: targetState.selection
7438
+ });
7439
+ }
7440
+ return Object.freeze(actions);
7441
+ }
7215
7442
  function findTableAction(runtime, actionHandle) {
7216
7443
  const action = findAnyTableAction(runtime, actionHandle);
7217
7444
  return action?.family === "table-text" ? action : null;
@@ -7231,6 +7458,27 @@ function findAnyTableAction(runtime, actionHandle) {
7231
7458
  }
7232
7459
  return null;
7233
7460
  }
7461
+ function findEditableTextAction(runtime, actionHandle) {
7462
+ if (!actionHandle.startsWith("scope-command:text-leaf:")) return null;
7463
+ const compiler = createScopeCompilerService(runtime);
7464
+ for (const scope of compiler.compileAllScopes()) {
7465
+ const action = editableTextActionsForScope(runtime, scope.handle).find(
7466
+ (candidate) => candidate.actionHandle === actionHandle
7467
+ );
7468
+ if (action) return action;
7469
+ }
7470
+ return null;
7471
+ }
7472
+ function findEditableTextActionByTargetKey(runtime, targetKey) {
7473
+ const compiler = createScopeCompilerService(runtime);
7474
+ for (const scope of compiler.compileAllScopes()) {
7475
+ const action = editableTextActionsForScope(runtime, scope.handle).find(
7476
+ (candidate) => candidate.editableTarget.targetKey === targetKey
7477
+ );
7478
+ if (action) return action;
7479
+ }
7480
+ return null;
7481
+ }
7234
7482
  function readDocumentPlanTarget(runtime) {
7235
7483
  const document = createInspectFamily(runtime).inspectDocument();
7236
7484
  return {
@@ -7287,6 +7535,18 @@ function readPlanTarget(runtime, target) {
7287
7535
  ])
7288
7536
  };
7289
7537
  }
7538
+ const editableText = findEditableTextAction(runtime, target.actionHandle);
7539
+ if (editableText) {
7540
+ return {
7541
+ ok: true,
7542
+ target: summarizeTarget(editableText),
7543
+ readback: {
7544
+ text: editableText.readback.text,
7545
+ excerpt: excerpt(editableText.readback.text),
7546
+ isEmpty: editableText.readback.isEmpty
7547
+ }
7548
+ };
7549
+ }
7290
7550
  return readPlanTableAction(runtime, target.actionHandle);
7291
7551
  }
7292
7552
  function readPlanTableAction(runtime, actionHandle) {
@@ -7349,6 +7609,15 @@ function checkPlanStepCapability(runtime, step, before) {
7349
7609
  "Regenerate the plan with a ScopeHandle or opaque actionHandle returned by L09."
7350
7610
  );
7351
7611
  }
7612
+ if (step.kind === "rewrite" && target.kind === "list-item") {
7613
+ return blockerWithOwner(
7614
+ "capability:list-item:authoritative-readback-required",
7615
+ "blocked",
7616
+ "List-item text replacement is not yet backed by an authoritative mutation/readback route.",
7617
+ "Use listOperation for numbering changes, or create an issue/explanation until L08/L07 list-item text replacement is proven.",
7618
+ "L08 semantic scopes and L07 runtime text commands"
7619
+ );
7620
+ }
7352
7621
  if (step.kind === "rewrite" && !target.canRewriteText) {
7353
7622
  return blocker(
7354
7623
  `actions:plan:target-not-rewriteable:${step.id}`,
@@ -7381,7 +7650,20 @@ function checkPlanStepCapability(runtime, step, before) {
7381
7650
  "Use a supported semantic scope or create an issue flag instead."
7382
7651
  );
7383
7652
  }
7384
- if (step.kind === "fieldRefresh" || step.kind === "tocRefresh" || step.kind === "bookmarkEdit" || step.kind === "hyperlinkDestinationEdit") {
7653
+ if (step.kind === "fieldRefresh" || step.kind === "tocRefresh" || step.kind === "bookmarkEdit" || step.kind === "hyperlinkDestinationEdit" || step.kind === "hyperlinkTextEdit") {
7654
+ if (step.kind === "hyperlinkTextEdit") {
7655
+ const resolved2 = resolveTarget(runtime, step.target);
7656
+ if (!resolved2.ok) return resolved2.blockerDetails[0] ?? null;
7657
+ if (resolved2.target.kind !== "editable-text" || resolved2.target.targetKind !== "hyperlink-text") {
7658
+ return blocker(
7659
+ `actions:hyperlink-text-edit:hyperlink-text-handle-required:${step.id}`,
7660
+ "unsupported",
7661
+ "Hyperlink display text plan steps require an exact hyperlink-text actionHandle.",
7662
+ "Regenerate the plan with a scope-command:text-leaf actionHandle returned by ai.actions.locateAll."
7663
+ );
7664
+ }
7665
+ return null;
7666
+ }
7385
7667
  const resolved = resolveScopeExactTarget(runtime, step.target, step.kind);
7386
7668
  if (!resolved.ok) return resolved.blockerDetails[0] ?? null;
7387
7669
  const targetRef = resolveModeledEditableTarget(runtime, resolved.target, step.kind);
@@ -7486,6 +7768,13 @@ function applyPlanStep(runtime, step, plan) {
7486
7768
  actorId: step.actorId ?? plan.actorId,
7487
7769
  origin: step.origin ?? plan.origin
7488
7770
  });
7771
+ case "hyperlinkTextEdit":
7772
+ return createActionsFamily(runtime).actions.hyperlinkTextEdit({
7773
+ target: step.target,
7774
+ text: step.text,
7775
+ actorId: step.actorId ?? plan.actorId,
7776
+ origin: step.origin ?? plan.origin
7777
+ });
7489
7778
  case "listOperation":
7490
7779
  return createActionsFamily(runtime).actions.listOperation({
7491
7780
  target: step.target,
@@ -7802,11 +8091,159 @@ function isTableFamilyScope(kind) {
7802
8091
  return kind === "table" || kind === "table-row" || kind === "table-cell";
7803
8092
  }
7804
8093
  function canRewriteScopeText(scope) {
8094
+ return !isTableFamilyScope(scope.kind) && scope.kind !== "list-item" && (scope.replaceability.level === "full" || scope.replaceability.level === "text-only");
8095
+ }
8096
+ function canInsertAdjacentScopeText(scope) {
7805
8097
  return !isTableFamilyScope(scope.kind) && (scope.replaceability.level === "full" || scope.replaceability.level === "text-only");
7806
8098
  }
8099
+ function scopeRewriteCapabilityBlocker(scope) {
8100
+ if (scope.kind === "list-item") {
8101
+ return blockerWithOwner(
8102
+ "capability:list-item:authoritative-readback-required",
8103
+ "blocked",
8104
+ "List-item text replacement is not yet backed by an authoritative mutation/readback route.",
8105
+ "Use listOperation for numbering changes, or create an issue/explanation until L08/L07 list-item text replacement is proven.",
8106
+ "L08 semantic scopes and L07 runtime text commands"
8107
+ );
8108
+ }
8109
+ if (!canRewriteScopeText(scope)) {
8110
+ return blocker(
8111
+ `actions:rewrite:target-not-rewriteable:${scope.handle.scopeId}`,
8112
+ "unsupported",
8113
+ "The target capability posture does not allow text rewrite.",
8114
+ "Use a supported text target, table text actionHandle, or create an issue flag instead."
8115
+ );
8116
+ }
8117
+ return null;
8118
+ }
7807
8119
  function canMarkScope(scope) {
7808
8120
  return !isTableFamilyScope(scope.kind) && scope.replaceability.level !== "blocked" && scope.replaceability.level !== "preserve-only";
7809
8121
  }
8122
+ function editableTextTargetState(document, target) {
8123
+ if (target.kind !== "hyperlink-text") return void 0;
8124
+ const resolved = resolveHyperlinkTarget(document, target);
8125
+ if (!resolved) return void 0;
8126
+ const text = collectInlineText2(resolved.hyperlink.children);
8127
+ return {
8128
+ readback: { text, isEmpty: text.length === 0 },
8129
+ selection: {
8130
+ anchor: resolved.from,
8131
+ head: resolved.to,
8132
+ isCollapsed: resolved.from === resolved.to,
8133
+ activeRange: {
8134
+ kind: "range",
8135
+ from: resolved.from,
8136
+ to: resolved.to,
8137
+ assoc: { start: -1, end: 1 }
8138
+ }
8139
+ }
8140
+ };
8141
+ }
8142
+ function resolveHyperlinkTarget(document, target) {
8143
+ const parsed = parseBlockInlinePath(target.blockPath);
8144
+ if (!parsed) return null;
8145
+ let blocks = document.content.children;
8146
+ let block;
8147
+ let row;
8148
+ let offset = 0;
8149
+ for (const token of parsed) {
8150
+ switch (token.kind) {
8151
+ case "block":
8152
+ for (let index = 0; index < token.index; index += 1) {
8153
+ offset += blockTextLength(blocks[index]);
8154
+ }
8155
+ block = blocks[token.index];
8156
+ row = void 0;
8157
+ if (!block) return null;
8158
+ break;
8159
+ case "row":
8160
+ if (block?.type !== "table") return null;
8161
+ row = block.rows[token.index];
8162
+ block = void 0;
8163
+ if (!row) return null;
8164
+ break;
8165
+ case "cell": {
8166
+ const cell = row?.cells[token.index];
8167
+ if (!cell) return null;
8168
+ blocks = cell.children;
8169
+ block = void 0;
8170
+ row = void 0;
8171
+ break;
8172
+ }
8173
+ case "inline": {
8174
+ if (block?.type !== "paragraph") return null;
8175
+ for (let index = 0; index < token.index; index += 1) {
8176
+ offset += inlineTextLength(block.children[index]);
8177
+ }
8178
+ const inline = block.children[token.index];
8179
+ if (inline?.type !== "hyperlink") return null;
8180
+ const length = collectInlineText2(inline.children).length;
8181
+ return { hyperlink: inline, from: offset, to: offset + length };
8182
+ }
8183
+ }
8184
+ }
8185
+ return null;
8186
+ }
8187
+ function parseBlockInlinePath(path) {
8188
+ if (!path.startsWith("main/")) return null;
8189
+ const tokens = [];
8190
+ const re = /(block|row|cell|inline)\[(\d+)\]/gu;
8191
+ let match;
8192
+ while ((match = re.exec(path)) !== null) {
8193
+ const kind = match[1];
8194
+ tokens.push({ kind, index: Number(match[2]) });
8195
+ }
8196
+ return tokens.length > 0 ? Object.freeze(tokens) : null;
8197
+ }
8198
+ function collectInlineText2(inlines) {
8199
+ let text = "";
8200
+ for (const inline of inlines) {
8201
+ switch (inline.type) {
8202
+ case "text":
8203
+ text += inline.text;
8204
+ break;
8205
+ case "hyperlink":
8206
+ case "field":
8207
+ text += collectInlineText2(inline.children);
8208
+ break;
8209
+ default:
8210
+ break;
8211
+ }
8212
+ }
8213
+ return text;
8214
+ }
8215
+ function blockTextLength(block) {
8216
+ if (!block) return 0;
8217
+ switch (block.type) {
8218
+ case "paragraph":
8219
+ return collectInlineText2(block.children).length;
8220
+ case "table":
8221
+ return block.rows.reduce(
8222
+ (rowSum, row) => rowSum + row.cells.reduce(
8223
+ (cellSum, cell) => cellSum + cell.children.reduce((blockSum, child) => blockSum + blockTextLength(child), 0),
8224
+ 0
8225
+ ),
8226
+ 0
8227
+ );
8228
+ case "sdt":
8229
+ case "custom_xml":
8230
+ return block.children.reduce((sum, child) => sum + blockTextLength(child), 0);
8231
+ default:
8232
+ return 0;
8233
+ }
8234
+ }
8235
+ function inlineTextLength(inline) {
8236
+ if (!inline) return 0;
8237
+ switch (inline.type) {
8238
+ case "text":
8239
+ return inline.text.length;
8240
+ case "hyperlink":
8241
+ case "field":
8242
+ return collectInlineText2(inline.children).length;
8243
+ default:
8244
+ return 0;
8245
+ }
8246
+ }
7810
8247
  function textMatches(text, query, matchCase) {
7811
8248
  if (matchCase) return text.includes(query);
7812
8249
  return text.toLocaleLowerCase().includes(query.toLocaleLowerCase());
@@ -7865,6 +8302,30 @@ function blockedApplyFromResolution(resolution) {
7865
8302
  blockerDetails: resolution.blockerDetails
7866
8303
  };
7867
8304
  }
8305
+ function withSuspectMutationApplyResult(result, stepOrScopeId, target) {
8306
+ const detail = blockerWithOwner(
8307
+ `actions:plan:suspect-mutation:${stepOrScopeId}`,
8308
+ "blocked",
8309
+ "The document changed even though the action did not return an applied result.",
8310
+ "Abort the remaining plan, inspect authoritative readback/export evidence, and route the target to the owning edit-target/readback layer before retrying.",
8311
+ "L08 semantic scopes and L07 runtime text commands"
8312
+ );
8313
+ return {
8314
+ ...result,
8315
+ status: "blocked",
8316
+ applied: false,
8317
+ changed: true,
8318
+ ...target ? { target } : {},
8319
+ posture: "suspect-mutation",
8320
+ blockers: Object.freeze([...result.blockers ?? [], detail.code]),
8321
+ blockerDetails: Object.freeze([...result.blockerDetails ?? [], detail])
8322
+ };
8323
+ }
8324
+ function isSuspectMutationStep(step) {
8325
+ return step.posture === "suspect-mutation" || (step.blockers ?? []).some(
8326
+ (code) => code.startsWith("actions:plan:suspect-mutation:") || code.startsWith("actions:rewrite:suspect-mutation:")
8327
+ );
8328
+ }
7868
8329
  function blockedPlan(mode, code, category, message, nextStep) {
7869
8330
  const detail = blocker(code, category, message, nextStep);
7870
8331
  return {