@beyondwork/docx-react-component 1.0.106 → 1.0.108
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/package.json +19 -5
- package/src/api/geometry-overlay-rects.ts +5 -0
- package/src/api/package-version.ts +1 -1
- package/src/api/page-anchor-id.ts +5 -0
- package/src/api/public-types.ts +16 -9
- package/src/api/table-node-specs.ts +6 -0
- package/src/api/v3/_create.ts +2 -1
- package/src/api/v3/_page-anchor-id.ts +52 -0
- package/src/api/v3/_runtime-handle.ts +92 -1
- package/src/api/v3/ai/_audit-time.ts +5 -0
- package/src/api/v3/ai/_pe2-evidence.ts +38 -0
- package/src/api/v3/ai/attach.ts +7 -2
- package/src/api/v3/ai/replacement.ts +101 -18
- package/src/api/v3/ai/resolve.ts +2 -2
- package/src/api/v3/ai/review.ts +177 -3
- package/src/api/v3/index.ts +1 -0
- package/src/api/v3/runtime/collab.ts +462 -0
- package/src/api/v3/runtime/document.ts +503 -20
- package/src/api/v3/runtime/geometry.ts +97 -0
- package/src/api/v3/runtime/layout.ts +744 -0
- package/src/api/v3/runtime/perf-probe.ts +14 -0
- package/src/api/v3/runtime/viewport.ts +9 -8
- package/src/api/v3/ui/_types.ts +149 -55
- package/src/api/v3/ui/chrome-preset-model.ts +5 -5
- package/src/api/v3/ui/debug.ts +115 -2
- package/src/api/v3/ui/index.ts +13 -0
- package/src/api/v3/ui/overlays.ts +0 -8
- package/src/api/v3/ui/surface.ts +56 -0
- package/src/api/v3/ui/viewport.ts +22 -9
- package/src/core/commands/image-commands.ts +1 -0
- package/src/core/commands/index.ts +6 -0
- package/src/core/schema/text-schema.ts +43 -5
- package/src/core/selection/mapping.ts +8 -1
- package/src/core/selection/review-anchors.ts +5 -1
- package/src/core/state/text-transaction.ts +8 -2
- package/src/io/export/serialize-revisions.ts +149 -1
- package/src/io/normalize/normalize-text.ts +6 -0
- package/src/io/ooxml/parse-bookmark-references.ts +55 -0
- package/src/io/ooxml/parse-fields.ts +24 -2
- package/src/io/ooxml/parse-headers-footers.ts +38 -5
- package/src/io/ooxml/parse-main-document.ts +153 -9
- package/src/io/ooxml/parse-numbering.ts +20 -0
- package/src/io/ooxml/parse-revisions.ts +19 -8
- package/src/io/opc/package-reader.ts +98 -8
- package/src/model/anchor.ts +4 -3
- package/src/model/canonical-document.ts +220 -2
- package/src/model/canonical-hash.ts +221 -0
- package/src/model/canonical-layout-inputs.ts +245 -6
- package/src/model/layout/index.ts +1 -0
- package/src/model/layout/page-graph-types.ts +118 -1
- package/src/model/review/revision-types.ts +14 -3
- package/src/preservation/store.ts +20 -4
- package/src/review/README.md +1 -1
- package/src/review/store/revision-actions.ts +14 -2
- package/src/runtime/collab/event-types.ts +67 -1
- package/src/runtime/collab/runtime-collab-sync.ts +177 -5
- package/src/runtime/diagnostics/layout-guard-warning.ts +18 -0
- package/src/runtime/document-heading-outline.ts +147 -0
- package/src/runtime/document-navigation.ts +8 -243
- package/src/runtime/document-runtime.ts +240 -97
- package/src/runtime/edit-dispatch/dispatch-text-command.ts +11 -0
- package/src/runtime/formatting/layout-inputs.ts +38 -5
- package/src/runtime/formatting/numbering/geometry.ts +28 -2
- package/src/runtime/geometry/adjacent-geometry-intake.ts +835 -0
- package/src/runtime/geometry/caret-geometry.ts +5 -6
- package/src/runtime/geometry/geometry-facet.ts +60 -10
- package/src/runtime/geometry/geometry-index.ts +591 -20
- package/src/runtime/geometry/geometry-types.ts +59 -0
- package/src/runtime/geometry/hit-test.ts +11 -1
- package/src/runtime/geometry/overlay-rects.ts +5 -3
- package/src/runtime/geometry/project-anchors.ts +1 -1
- package/src/runtime/geometry/word-layout-v2-line-intake.ts +323 -0
- package/src/runtime/layout/index.ts +6 -0
- package/src/runtime/layout/layout-engine-instance.ts +6 -1
- package/src/runtime/layout/layout-engine-version.ts +181 -16
- package/src/runtime/layout/layout-facet-types.ts +6 -0
- package/src/runtime/layout/page-graph.ts +21 -4
- package/src/runtime/layout/paginated-layout-engine.ts +139 -15
- package/src/runtime/layout/project-block-fragments.ts +265 -7
- package/src/runtime/layout/public-facet.ts +78 -24
- package/src/runtime/layout/table-row-continuation-contract.ts +107 -0
- package/src/runtime/layout/table-row-split.ts +92 -35
- package/src/runtime/prerender/cache-envelope.ts +2 -2
- package/src/runtime/prerender/cache-key.ts +5 -4
- package/src/runtime/prerender/customxml-cache.ts +0 -1
- package/src/runtime/render/render-kernel.ts +1 -1
- package/src/runtime/revision-runtime.ts +112 -10
- package/src/runtime/scopes/_scope-dependencies.ts +1 -0
- package/src/runtime/scopes/action-validation.ts +22 -2
- package/src/runtime/scopes/capabilities.ts +316 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +14 -0
- package/src/runtime/scopes/compiler-service.ts +108 -4
- package/src/runtime/scopes/content-control-evidence.ts +79 -0
- package/src/runtime/scopes/create-issue.ts +5 -5
- package/src/runtime/scopes/evidence.ts +91 -0
- package/src/runtime/scopes/formatting/apply.ts +2 -0
- package/src/runtime/scopes/geometry-evidence.ts +130 -0
- package/src/runtime/scopes/index.ts +54 -0
- package/src/runtime/scopes/issue-lifecycle.ts +224 -0
- package/src/runtime/scopes/layout-evidence.ts +374 -0
- package/src/runtime/scopes/multi-paragraph-refusal.ts +37 -0
- package/src/runtime/scopes/preservation-boundary.ts +7 -1
- package/src/runtime/scopes/replacement/apply.ts +97 -34
- package/src/runtime/scopes/scope-kinds/paragraph.ts +108 -12
- package/src/runtime/scopes/semantic-scope-types.ts +242 -3
- package/src/runtime/scopes/visualization.ts +28 -0
- package/src/runtime/surface-projection.ts +44 -5
- package/src/runtime/telemetry/perf-probe.ts +216 -0
- package/src/runtime/virtualized-rendering.ts +36 -1
- package/src/runtime/workflow/ai-issue-lifecycle.ts +253 -0
- package/src/runtime/workflow/coordinator.ts +39 -11
- package/src/runtime/workflow/derived-scope-resolver.ts +63 -9
- package/src/runtime/workflow/index.ts +3 -0
- package/src/runtime/workflow/overlay-lane-types.ts +58 -0
- package/src/runtime/workflow/overlay-lanes.ts +168 -10
- package/src/runtime/workflow/overlay-store.ts +2 -2
- package/src/runtime/workflow/redline-posture-calibration.ts +257 -0
- package/src/runtime/workflow/word-field-matrix-calibration.ts +231 -0
- package/src/session/_sync-legacy.ts +17 -27
- package/src/session/import/loader.ts +6 -4
- package/src/session/import/source-package-evidence.ts +186 -2
- package/src/session/index.ts +5 -6
- package/src/session/session.ts +30 -56
- package/src/session/types.ts +8 -13
- package/src/shell/session-bootstrap.ts +155 -81
- package/src/ui/WordReviewEditor.tsx +520 -12
- package/src/ui/editor-shell-view.tsx +14 -4
- package/src/ui/editor-surface-controller.tsx +5 -3
- package/src/ui/headless/selection-tool-resolver.ts +1 -2
- package/src/ui/presence-overlay-lane.ts +0 -1
- package/src/ui/ui-controller-factory.ts +7 -0
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +5 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +105 -5
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +7 -0
- package/src/ui-tailwind/chrome/layer-debug-contracts.ts +208 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +13 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +11 -3
- package/src/ui-tailwind/chrome/tw-command-palette.tsx +36 -6
- package/src/ui-tailwind/chrome/tw-context-menu.tsx +6 -1
- package/src/ui-tailwind/chrome/tw-display-mode-selector.tsx +42 -109
- package/src/ui-tailwind/chrome/tw-inline-find-bar.tsx +26 -6
- package/src/ui-tailwind/chrome/tw-navigation-command-bar.tsx +328 -0
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +8 -4
- package/src/ui-tailwind/chrome/tw-runtime-repl-dialog.tsx +129 -1
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +19 -5
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +5 -1
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +28 -12
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +30 -3
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +116 -10
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +223 -94
- package/src/ui-tailwind/chrome-overlay/tw-presence-overlay-lane.tsx +157 -0
- package/src/ui-tailwind/chrome-overlay/tw-review-overlay-lane-markers.tsx +259 -0
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +5 -2
- package/src/ui-tailwind/chrome-overlay/tw-substrate-overlay-lanes.tsx +314 -0
- package/src/ui-tailwind/debug/README.md +4 -1
- package/src/ui-tailwind/debug/layer11-consumer-readiness.ts +272 -0
- package/src/ui-tailwind/debug/layer11-word-field-matrix-evidence.ts +160 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +14 -215
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +42 -0
- package/src/ui-tailwind/editor-surface/pm-position-map.ts +38 -2
- package/src/ui-tailwind/editor-surface/pm-schema.ts +14 -4
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +34 -5
- package/src/ui-tailwind/editor-surface/runtime-decoration-plugin.ts +9 -19
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +2 -2
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +145 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +16 -11
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +8 -10
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +3 -0
- package/src/ui-tailwind/page-stack/tw-page-chrome-entry.tsx +4 -2
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +60 -20
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +16 -11
- package/src/ui-tailwind/review/tw-health-panel.tsx +36 -17
- package/src/ui-tailwind/review/tw-review-rail.tsx +7 -4
- package/src/ui-tailwind/review-workspace/diagnostics-visibility.ts +44 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +11 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +16 -1
- package/src/ui-tailwind/review-workspace/types.ts +26 -12
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +40 -11
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +2 -1
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +15 -26
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +35 -18
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +41 -32
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +2 -1
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +2 -1
- package/src/ui-tailwind/status/tw-status-bar.tsx +6 -5
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +52 -80
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +12 -48
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +9 -4
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +328 -361
- package/src/ui-tailwind/tw-review-workspace.tsx +152 -286
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope action capability projection.
|
|
3
|
+
*
|
|
4
|
+
* This module reports what the shipped L08 compiler/runtime can lower today.
|
|
5
|
+
* It does not validate a specific payload and does not authorize a mutation;
|
|
6
|
+
* every apply path still re-runs validation and compile.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
ScopeContentControlEvidence,
|
|
11
|
+
ScopeGeometryEvidence,
|
|
12
|
+
ScopeLayoutEvidence,
|
|
13
|
+
ScopeCapabilities,
|
|
14
|
+
ScopeCapabilityVerdict,
|
|
15
|
+
SemanticScope,
|
|
16
|
+
SemanticScopeKind,
|
|
17
|
+
} from "./semantic-scope-types.ts";
|
|
18
|
+
import {
|
|
19
|
+
MULTI_PARAGRAPH_REPLACEMENT_REFUSAL,
|
|
20
|
+
multiParagraphReplacementBlockers,
|
|
21
|
+
} from "./multi-paragraph-refusal.ts";
|
|
22
|
+
|
|
23
|
+
const PARAGRAPH_LIKE = new Set<SemanticScopeKind>([
|
|
24
|
+
"paragraph",
|
|
25
|
+
"heading",
|
|
26
|
+
"list-item",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
const FORMATTING_SUPPORTED = new Set<SemanticScopeKind>([
|
|
30
|
+
"paragraph",
|
|
31
|
+
"heading",
|
|
32
|
+
"list-item",
|
|
33
|
+
"scope",
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const METADATA_SUPPORTED = new Set<SemanticScopeKind>([
|
|
37
|
+
"paragraph",
|
|
38
|
+
"heading",
|
|
39
|
+
"list-item",
|
|
40
|
+
"table",
|
|
41
|
+
"table-row",
|
|
42
|
+
"table-cell",
|
|
43
|
+
"scope",
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
export interface ScopeCapabilityContext {
|
|
47
|
+
readonly layout?: ScopeLayoutEvidence;
|
|
48
|
+
readonly geometry?: ScopeGeometryEvidence;
|
|
49
|
+
readonly contentControls?: ScopeContentControlEvidence;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function freezeList(values: readonly string[]): readonly string[] {
|
|
53
|
+
return Object.freeze([...values]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function supported(
|
|
57
|
+
reason: string,
|
|
58
|
+
warnings: readonly string[] = [],
|
|
59
|
+
): ScopeCapabilityVerdict {
|
|
60
|
+
const hasWarnings = warnings.length > 0;
|
|
61
|
+
return {
|
|
62
|
+
supported: true,
|
|
63
|
+
status: hasWarnings ? "degraded" : "supported",
|
|
64
|
+
posture: hasWarnings ? "warn-and-proceed" : "supported",
|
|
65
|
+
reason,
|
|
66
|
+
...(hasWarnings ? { warnings: freezeList(warnings) } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function unsupported(
|
|
71
|
+
reason: string,
|
|
72
|
+
blockers: readonly string[] = [reason],
|
|
73
|
+
warnings: readonly string[] = [],
|
|
74
|
+
): ScopeCapabilityVerdict {
|
|
75
|
+
return {
|
|
76
|
+
supported: false,
|
|
77
|
+
status: "unsupported",
|
|
78
|
+
posture: "hard-refusal",
|
|
79
|
+
reason,
|
|
80
|
+
blockers: freezeList(blockers),
|
|
81
|
+
...(warnings.length > 0 ? { warnings: freezeList(warnings) } : {}),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function blocked(
|
|
86
|
+
reason: string,
|
|
87
|
+
blockers: readonly string[] = [reason],
|
|
88
|
+
): ScopeCapabilityVerdict {
|
|
89
|
+
return {
|
|
90
|
+
supported: false,
|
|
91
|
+
status: "blocked",
|
|
92
|
+
posture: "hard-refusal",
|
|
93
|
+
reason,
|
|
94
|
+
blockers: freezeList(blockers),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function guardBlocker(scope: SemanticScope): string | null {
|
|
99
|
+
switch (scope.workflow.effectiveMode) {
|
|
100
|
+
case "view":
|
|
101
|
+
return "guard:view-mode-active";
|
|
102
|
+
case "comment":
|
|
103
|
+
return "guard:comment-only";
|
|
104
|
+
case "blocked": {
|
|
105
|
+
const [first] = scope.workflow.blockedReasons ?? [];
|
|
106
|
+
return first ? `guard:block-${first}` : "guard:block-scope-overlay";
|
|
107
|
+
}
|
|
108
|
+
default:
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function operationRefusal(scope: SemanticScope): string {
|
|
114
|
+
return `compile-refused:${scope.kind}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function contentControlBlockers(
|
|
118
|
+
context: ScopeCapabilityContext | undefined,
|
|
119
|
+
): readonly string[] {
|
|
120
|
+
const entries = context?.contentControls?.entries ?? [];
|
|
121
|
+
if (entries.length === 0) return [];
|
|
122
|
+
return freezeList(entries.map((entry) => `preserve:content-control:${entry.evidenceId}`));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function evidenceWarnings(
|
|
126
|
+
context: ScopeCapabilityContext | undefined,
|
|
127
|
+
): readonly string[] {
|
|
128
|
+
const warnings: string[] = [];
|
|
129
|
+
if (context?.layout) {
|
|
130
|
+
if (
|
|
131
|
+
context.layout.status === "requires-rehydration" ||
|
|
132
|
+
context.layout.status === "unavailable" ||
|
|
133
|
+
context.layout.completeness !== "complete"
|
|
134
|
+
) {
|
|
135
|
+
warnings.push(`layout:${context.layout.completeness}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (context?.geometry) {
|
|
139
|
+
if (context.geometry.requiresRehydration) {
|
|
140
|
+
warnings.push("geometry:requires-rehydration");
|
|
141
|
+
} else if (context.geometry.status === "unavailable") {
|
|
142
|
+
warnings.push("geometry:unavailable");
|
|
143
|
+
}
|
|
144
|
+
if (context.geometry.continuationState?.crossesPageBoundary) {
|
|
145
|
+
warnings.push("geometry:crosses-page-boundary");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return freezeList(warnings);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function insertCapability(
|
|
152
|
+
scope: SemanticScope,
|
|
153
|
+
edge: "before" | "after",
|
|
154
|
+
context?: ScopeCapabilityContext,
|
|
155
|
+
): ScopeCapabilityVerdict {
|
|
156
|
+
const guard = guardBlocker(scope);
|
|
157
|
+
if (guard) return blocked(guard);
|
|
158
|
+
|
|
159
|
+
if (!PARAGRAPH_LIKE.has(scope.kind)) {
|
|
160
|
+
return unsupported(operationRefusal(scope));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (
|
|
164
|
+
scope.replaceability.level === "blocked" ||
|
|
165
|
+
scope.replaceability.level === "preserve-only"
|
|
166
|
+
) {
|
|
167
|
+
const reason = scope.replaceability.reason
|
|
168
|
+
? `replaceability:${scope.replaceability.reason}`
|
|
169
|
+
: `replaceability:${scope.replaceability.level}`;
|
|
170
|
+
return unsupported(reason);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return supported(
|
|
174
|
+
`compile-supported:paragraph-like:insert-${edge}`,
|
|
175
|
+
[
|
|
176
|
+
...(scope.workflow.effectiveMode === "suggest" ? ["guard:suggest-mode"] : []),
|
|
177
|
+
...evidenceWarnings(context),
|
|
178
|
+
],
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function replaceTextCapability(
|
|
183
|
+
scope: SemanticScope,
|
|
184
|
+
context?: ScopeCapabilityContext,
|
|
185
|
+
): ScopeCapabilityVerdict {
|
|
186
|
+
const guard = guardBlocker(scope);
|
|
187
|
+
if (guard) return blocked(guard);
|
|
188
|
+
|
|
189
|
+
const contentControls = contentControlBlockers(context);
|
|
190
|
+
if (contentControls.length > 0) {
|
|
191
|
+
return blocked("preserve:content-control", contentControls);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!PARAGRAPH_LIKE.has(scope.kind)) {
|
|
195
|
+
const reason =
|
|
196
|
+
scope.kind === "scope" && scope.replaceability.reason
|
|
197
|
+
? MULTI_PARAGRAPH_REPLACEMENT_REFUSAL
|
|
198
|
+
: `compile-refused:${scope.kind}`;
|
|
199
|
+
return unsupported(
|
|
200
|
+
reason,
|
|
201
|
+
scope.kind === "scope"
|
|
202
|
+
? multiParagraphReplacementBlockers("text")
|
|
203
|
+
: [reason],
|
|
204
|
+
evidenceWarnings(context),
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (
|
|
209
|
+
scope.replaceability.level === "blocked" ||
|
|
210
|
+
scope.replaceability.level === "preserve-only" ||
|
|
211
|
+
scope.replaceability.level === "formatting-only"
|
|
212
|
+
) {
|
|
213
|
+
const reason = scope.replaceability.reason
|
|
214
|
+
? `replaceability:${scope.replaceability.reason}`
|
|
215
|
+
: `replaceability:${scope.replaceability.level}`;
|
|
216
|
+
return unsupported(reason);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return supported(
|
|
220
|
+
"compile-supported:paragraph-like:text-replace",
|
|
221
|
+
[
|
|
222
|
+
...(scope.workflow.effectiveMode === "suggest" ? ["guard:suggest-mode"] : []),
|
|
223
|
+
...evidenceWarnings(context),
|
|
224
|
+
],
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function replaceFragmentCapability(
|
|
229
|
+
scope: SemanticScope,
|
|
230
|
+
context?: ScopeCapabilityContext,
|
|
231
|
+
): ScopeCapabilityVerdict {
|
|
232
|
+
const guard = guardBlocker(scope);
|
|
233
|
+
if (guard) return blocked(guard);
|
|
234
|
+
|
|
235
|
+
const contentControls = contentControlBlockers(context);
|
|
236
|
+
if (contentControls.length > 0) {
|
|
237
|
+
return blocked("preserve:content-control", contentControls);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!PARAGRAPH_LIKE.has(scope.kind)) {
|
|
241
|
+
const reason =
|
|
242
|
+
scope.kind === "scope" && scope.replaceability.reason
|
|
243
|
+
? MULTI_PARAGRAPH_REPLACEMENT_REFUSAL
|
|
244
|
+
: `compile-refused:${scope.kind}`;
|
|
245
|
+
return unsupported(
|
|
246
|
+
reason,
|
|
247
|
+
scope.kind === "scope"
|
|
248
|
+
? multiParagraphReplacementBlockers("fragment")
|
|
249
|
+
: [reason],
|
|
250
|
+
evidenceWarnings(context),
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (scope.workflow.effectiveMode === "suggest") {
|
|
255
|
+
return unsupported(
|
|
256
|
+
`compile-refused:${scope.kind}:structured-suggesting-not-implemented`,
|
|
257
|
+
[`compile-refused:${scope.kind}:structured-suggesting-not-implemented`],
|
|
258
|
+
["guard:suggest-mode"],
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return supported(
|
|
263
|
+
"compile-supported:paragraph-like:fragment-replace",
|
|
264
|
+
evidenceWarnings(context),
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function formattingCapability(
|
|
269
|
+
scope: SemanticScope,
|
|
270
|
+
context?: ScopeCapabilityContext,
|
|
271
|
+
): ScopeCapabilityVerdict {
|
|
272
|
+
const guard = guardBlocker(scope);
|
|
273
|
+
if (guard) return blocked(guard);
|
|
274
|
+
|
|
275
|
+
if (!FORMATTING_SUPPORTED.has(scope.kind)) {
|
|
276
|
+
return unsupported(`compile-refused:${scope.kind}:formatting-not-implemented`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (scope.workflow.effectiveMode === "suggest") {
|
|
280
|
+
return unsupported(
|
|
281
|
+
`compile-refused:${scope.kind}:formatting-suggesting-not-implemented`,
|
|
282
|
+
[`compile-refused:${scope.kind}:formatting-suggesting-not-implemented`],
|
|
283
|
+
["guard:suggest-mode"],
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return supported("compile-supported:scope-formatting", evidenceWarnings(context));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function metadataCapability(scope: SemanticScope): ScopeCapabilityVerdict {
|
|
291
|
+
if (METADATA_SUPPORTED.has(scope.kind)) {
|
|
292
|
+
return supported(
|
|
293
|
+
scope.kind === "table" ||
|
|
294
|
+
scope.kind === "table-row" ||
|
|
295
|
+
scope.kind === "table-cell"
|
|
296
|
+
? "metadata-supported:derived-table-family"
|
|
297
|
+
: "metadata-supported:scope-id",
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
return unsupported(`scope-not-resolvable:${scope.handle.scopeId}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function deriveScopeCapabilities(
|
|
304
|
+
scope: SemanticScope,
|
|
305
|
+
context: ScopeCapabilityContext = {},
|
|
306
|
+
): ScopeCapabilities {
|
|
307
|
+
return {
|
|
308
|
+
canReplaceText: replaceTextCapability(scope, context),
|
|
309
|
+
canReplaceFragment: replaceFragmentCapability(scope, context),
|
|
310
|
+
canInsertBefore: insertCapability(scope, "before", context),
|
|
311
|
+
canInsertAfter: insertCapability(scope, "after", context),
|
|
312
|
+
canApplyFormatting: formattingCapability(scope, context),
|
|
313
|
+
canClearFormattingLayer: formattingCapability(scope, context),
|
|
314
|
+
canAttachMetadata: metadataCapability(scope),
|
|
315
|
+
};
|
|
316
|
+
}
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
WorkflowMetadataEntry,
|
|
18
18
|
WorkflowOverlay,
|
|
19
19
|
} from "./_scope-dependencies.ts";
|
|
20
|
+
import type { ScopeGeometryEvidenceProvider } from "./geometry-evidence.ts";
|
|
20
21
|
|
|
21
22
|
import {
|
|
22
23
|
buildParagraphIndexMap,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
import type { EnumeratedScope } from "./enumerate-scopes.ts";
|
|
27
28
|
import { enumerateScopes } from "./enumerate-scopes.ts";
|
|
28
29
|
import { composeEvidence } from "./evidence.ts";
|
|
30
|
+
import type { ScopeLayoutEvidenceProvider } from "./layout-evidence.ts";
|
|
29
31
|
import type {
|
|
30
32
|
ScopeBundle,
|
|
31
33
|
ScopeBundleNeighborhood,
|
|
@@ -47,6 +49,16 @@ export interface ScopeBundleInputs {
|
|
|
47
49
|
* to walk the metadata snapshot.
|
|
48
50
|
*/
|
|
49
51
|
readonly workflowMetadataEntries?: readonly WorkflowMetadataEntry[];
|
|
52
|
+
/**
|
|
53
|
+
* Optional Layer-05 replacement-envelope read seam. When omitted, bundle
|
|
54
|
+
* evidence records geometry as unavailable rather than synthesizing rects.
|
|
55
|
+
*/
|
|
56
|
+
readonly geometry?: ScopeGeometryEvidenceProvider;
|
|
57
|
+
/**
|
|
58
|
+
* Optional lower-layer layout evidence seam. When absent, bundle evidence
|
|
59
|
+
* records layout as unavailable instead of deriving page slices in L08.
|
|
60
|
+
*/
|
|
61
|
+
readonly layout?: ScopeLayoutEvidenceProvider;
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
/**
|
|
@@ -126,6 +138,8 @@ export function compileScopeBundle(
|
|
|
126
138
|
...(inputs.workflowMetadataEntries
|
|
127
139
|
? { workflowMetadataEntries: inputs.workflowMetadataEntries }
|
|
128
140
|
: {}),
|
|
141
|
+
...(inputs.geometry ? { geometry: inputs.geometry } : {}),
|
|
142
|
+
...(inputs.layout ? { layout: inputs.layout } : {}),
|
|
129
143
|
});
|
|
130
144
|
return {
|
|
131
145
|
scope,
|
|
@@ -37,10 +37,12 @@ import type {
|
|
|
37
37
|
WorkflowMetadataEntry,
|
|
38
38
|
WorkflowMetadataSnapshot,
|
|
39
39
|
WorkflowOverlay,
|
|
40
|
+
WorkflowEventOrigin,
|
|
40
41
|
} from "./_scope-dependencies.ts";
|
|
41
42
|
import type { CanonicalDocumentEnvelope } from "../../core/state/editor-state.ts";
|
|
42
43
|
import type { TelemetryBus } from "../debug/telemetry-bus.ts";
|
|
43
44
|
import type { AIAction } from "../workflow/ai-action-policy.ts";
|
|
45
|
+
import type { ScopeGeometryEvidenceProvider } from "./geometry-evidence.ts";
|
|
44
46
|
|
|
45
47
|
import {
|
|
46
48
|
buildParagraphIndexMap,
|
|
@@ -49,6 +51,12 @@ import {
|
|
|
49
51
|
} from "./compile-scope.ts";
|
|
50
52
|
import { compileScopeBundleById } from "./compile-scope-bundle.ts";
|
|
51
53
|
import { enumerateScopes, type EnumeratedScope } from "./enumerate-scopes.ts";
|
|
54
|
+
import {
|
|
55
|
+
collectTopLevelTableBlockIdsFromRenderSnapshot,
|
|
56
|
+
createRuntimeTableFrameLayoutEvidenceProvider,
|
|
57
|
+
type ScopeRuntimeLayoutEvidenceSource,
|
|
58
|
+
type ScopeRuntimeRenderSnapshotLike,
|
|
59
|
+
} from "./layout-evidence.ts";
|
|
52
60
|
import {
|
|
53
61
|
attachExplanation,
|
|
54
62
|
type AttachExplanationResult,
|
|
@@ -59,6 +67,12 @@ import {
|
|
|
59
67
|
type IssueSeverity,
|
|
60
68
|
type IssueStatus,
|
|
61
69
|
} from "./create-issue.ts";
|
|
70
|
+
import {
|
|
71
|
+
resolveIssueLifecycleTarget,
|
|
72
|
+
transitionScopeIssueLifecycle,
|
|
73
|
+
type IssueLifecycleAction,
|
|
74
|
+
type TransitionScopeIssueLifecycleResult,
|
|
75
|
+
} from "./issue-lifecycle.ts";
|
|
62
76
|
import {
|
|
63
77
|
applyScopeReplacement,
|
|
64
78
|
type ApplyScopeReplacementResult,
|
|
@@ -69,12 +83,12 @@ import {
|
|
|
69
83
|
} from "./formatting/apply.ts";
|
|
70
84
|
import { proposeReplacement } from "./replacement/propose.ts";
|
|
71
85
|
import type {
|
|
72
|
-
ReplacementOperationKind,
|
|
73
86
|
ReplacementPreservePolicy,
|
|
74
87
|
ReplacementScope,
|
|
75
88
|
RuntimeOperationPlan,
|
|
76
89
|
ScopeFormattingAction,
|
|
77
90
|
ScopeFormattingScope,
|
|
91
|
+
ScopeReplacementOperationKind,
|
|
78
92
|
ScopeBundle,
|
|
79
93
|
ScopeHandle,
|
|
80
94
|
SemanticScope,
|
|
@@ -98,10 +112,16 @@ export interface CompilerServiceRuntime {
|
|
|
98
112
|
getInteractionGuardSnapshot(): InteractionGuardSnapshot;
|
|
99
113
|
getCompatibilityReport(): CompatibilityReport;
|
|
100
114
|
getWorkflowMetadataSnapshot(): WorkflowMetadataSnapshot;
|
|
101
|
-
setWorkflowMetadataEntries(
|
|
115
|
+
setWorkflowMetadataEntries(
|
|
116
|
+
entries: readonly WorkflowMetadataEntry[],
|
|
117
|
+
origin?: WorkflowEventOrigin,
|
|
118
|
+
): void;
|
|
119
|
+
getRenderSnapshot?(): ScopeRuntimeRenderSnapshotLike;
|
|
102
120
|
getSessionState(): ScopeSessionState;
|
|
103
121
|
applyScopeReplacement(plan: RuntimeOperationPlan): void;
|
|
104
122
|
applyScopeFormatting(plan: RuntimeOperationPlan): boolean;
|
|
123
|
+
readonly geometry?: ScopeGeometryEvidenceProvider;
|
|
124
|
+
readonly layout?: ScopeRuntimeLayoutEvidenceSource;
|
|
105
125
|
debug?: { bus: TelemetryBus };
|
|
106
126
|
}
|
|
107
127
|
|
|
@@ -113,7 +133,7 @@ export interface CompileScopeByIdResult {
|
|
|
113
133
|
|
|
114
134
|
export interface ApplyReplacementRequest {
|
|
115
135
|
readonly targetScopeId: string;
|
|
116
|
-
readonly operation:
|
|
136
|
+
readonly operation: ScopeReplacementOperationKind;
|
|
117
137
|
/**
|
|
118
138
|
* Flat text payload. Shorthand for
|
|
119
139
|
* `proposedContent: {kind: "text", text}`. Ignored when
|
|
@@ -165,6 +185,14 @@ export interface CreateIssueRequest {
|
|
|
165
185
|
readonly status?: IssueStatus;
|
|
166
186
|
}
|
|
167
187
|
|
|
188
|
+
export interface TransitionIssueLifecycleRequest {
|
|
189
|
+
readonly issueId: string;
|
|
190
|
+
readonly action: IssueLifecycleAction;
|
|
191
|
+
readonly actorId: string;
|
|
192
|
+
readonly origin: "ui" | "agent" | "host";
|
|
193
|
+
readonly emittedAtUtc: string;
|
|
194
|
+
}
|
|
195
|
+
|
|
168
196
|
export interface ScopeCompilerService {
|
|
169
197
|
/**
|
|
170
198
|
* Enumerate + compile every live scope in the document. Per-call the
|
|
@@ -197,7 +225,7 @@ export interface ScopeCompilerService {
|
|
|
197
225
|
buildReplacementScope(
|
|
198
226
|
targetHandle: ScopeHandle,
|
|
199
227
|
input: {
|
|
200
|
-
readonly operation:
|
|
228
|
+
readonly operation: ScopeReplacementOperationKind;
|
|
201
229
|
readonly proposedText?: string;
|
|
202
230
|
readonly formatting?: ReplacementScope["formatting"];
|
|
203
231
|
readonly preserve?: ReplacementPreservePolicy;
|
|
@@ -238,6 +266,17 @@ export interface ScopeCompilerService {
|
|
|
238
266
|
* overlay-only constraint as `attachExplanation`.
|
|
239
267
|
*/
|
|
240
268
|
createIssue(request: CreateIssueRequest): CreateIssueResult;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Resolve/reopen an existing `ai.issue` metadata entry through the L06
|
|
272
|
+
* durable lifecycle substrate, but only after its scope target still compiles
|
|
273
|
+
* through Layer 08. This is intentionally not a public L09 API yet; it is the
|
|
274
|
+
* scope/evidence join that L09 will consume when `ai.resolveIssue` /
|
|
275
|
+
* `ai.reopenIssue` graduate.
|
|
276
|
+
*/
|
|
277
|
+
transitionIssueLifecycle(
|
|
278
|
+
request: TransitionIssueLifecycleRequest,
|
|
279
|
+
): TransitionScopeIssueLifecycleResult;
|
|
241
280
|
}
|
|
242
281
|
|
|
243
282
|
/**
|
|
@@ -324,12 +363,24 @@ export function createScopeCompilerService(
|
|
|
324
363
|
// operations go through `attachScopeMetadata` via this same
|
|
325
364
|
// runtime surface, so the snapshot is always fresh here.
|
|
326
365
|
const workflowMetadataEntries = runtime.getWorkflowMetadataSnapshot().entries;
|
|
366
|
+
const layout =
|
|
367
|
+
runtime.layout
|
|
368
|
+
? createRuntimeTableFrameLayoutEvidenceProvider({
|
|
369
|
+
layout: runtime.layout,
|
|
370
|
+
tableBlockIdsByBlockIndex:
|
|
371
|
+
collectTopLevelTableBlockIdsFromRenderSnapshot(
|
|
372
|
+
runtime.getRenderSnapshot?.(),
|
|
373
|
+
),
|
|
374
|
+
})
|
|
375
|
+
: undefined;
|
|
327
376
|
return compileScopeBundleById(scopeId, {
|
|
328
377
|
document,
|
|
329
378
|
...(overlay ? { overlay } : {}),
|
|
330
379
|
nowUtc,
|
|
331
380
|
catalog: document.styles,
|
|
332
381
|
workflowMetadataEntries,
|
|
382
|
+
...(runtime.geometry ? { geometry: runtime.geometry } : {}),
|
|
383
|
+
...(layout ? { layout } : {}),
|
|
333
384
|
});
|
|
334
385
|
},
|
|
335
386
|
|
|
@@ -361,6 +412,7 @@ export function createScopeCompilerService(
|
|
|
361
412
|
reason: "scope-not-resolvable",
|
|
362
413
|
validation: {
|
|
363
414
|
safe: false,
|
|
415
|
+
posture: "hard-refusal",
|
|
364
416
|
blockedReasons: Object.freeze([
|
|
365
417
|
`scope-not-resolvable:${request.targetScopeId}`,
|
|
366
418
|
]),
|
|
@@ -400,6 +452,7 @@ export function createScopeCompilerService(
|
|
|
400
452
|
runtime.getInteractionGuardSnapshot(),
|
|
401
453
|
getCompatibilityReport: () => runtime.getCompatibilityReport(),
|
|
402
454
|
applyScopeReplacement: (plan) => runtime.applyScopeReplacement(plan),
|
|
455
|
+
verifyReadback: true,
|
|
403
456
|
},
|
|
404
457
|
proposed,
|
|
405
458
|
...(request.actionId ? { actionId: request.actionId } : {}),
|
|
@@ -418,6 +471,7 @@ export function createScopeCompilerService(
|
|
|
418
471
|
reason: "scope-not-resolvable",
|
|
419
472
|
validation: {
|
|
420
473
|
safe: false,
|
|
474
|
+
posture: "hard-refusal",
|
|
421
475
|
blockedReasons: Object.freeze([
|
|
422
476
|
`scope-not-resolvable:${request.targetScopeId}`,
|
|
423
477
|
]),
|
|
@@ -498,5 +552,55 @@ export function createScopeCompilerService(
|
|
|
498
552
|
},
|
|
499
553
|
);
|
|
500
554
|
},
|
|
555
|
+
|
|
556
|
+
transitionIssueLifecycle(
|
|
557
|
+
request: TransitionIssueLifecycleRequest,
|
|
558
|
+
): TransitionScopeIssueLifecycleResult {
|
|
559
|
+
const target = resolveIssueLifecycleTarget(
|
|
560
|
+
runtime.getWorkflowMetadataSnapshot(),
|
|
561
|
+
request.issueId,
|
|
562
|
+
);
|
|
563
|
+
if (!target) {
|
|
564
|
+
const reason = `issue-not-found:${request.issueId}`;
|
|
565
|
+
return {
|
|
566
|
+
transitioned: false,
|
|
567
|
+
issueId: request.issueId,
|
|
568
|
+
reason,
|
|
569
|
+
blockers: Object.freeze([reason]),
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const compiled = this.compileScopeById(target.scopeId);
|
|
574
|
+
if (!compiled) {
|
|
575
|
+
const reason = `scope-not-resolvable:${target.scopeId}`;
|
|
576
|
+
return {
|
|
577
|
+
transitioned: false,
|
|
578
|
+
issueId: target.issueId,
|
|
579
|
+
reason,
|
|
580
|
+
blockers: Object.freeze([reason]),
|
|
581
|
+
scopeId: target.scopeId,
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const documentBefore = runtime.getCanonicalDocument();
|
|
586
|
+
const result = transitionScopeIssueLifecycle({
|
|
587
|
+
runtime: {
|
|
588
|
+
getCanonicalDocument: () => runtime.getCanonicalDocument(),
|
|
589
|
+
getWorkflowMetadataSnapshot: () =>
|
|
590
|
+
runtime.getWorkflowMetadataSnapshot(),
|
|
591
|
+
setWorkflowMetadataEntries: (entries, origin) =>
|
|
592
|
+
runtime.setWorkflowMetadataEntries([...entries], origin),
|
|
593
|
+
},
|
|
594
|
+
documentBefore,
|
|
595
|
+
targetScopeSnapshot: compiled.scope,
|
|
596
|
+
issueId: target.issueId,
|
|
597
|
+
action: request.action,
|
|
598
|
+
actorId: request.actorId,
|
|
599
|
+
origin: request.origin,
|
|
600
|
+
emittedAtUtc: request.emittedAtUtc,
|
|
601
|
+
...(runtime.debug?.bus ? { bus: runtime.debug.bus } : {}),
|
|
602
|
+
});
|
|
603
|
+
return result;
|
|
604
|
+
},
|
|
501
605
|
};
|
|
502
606
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-control / SDT evidence for scope bundles and preservation checks.
|
|
3
|
+
*
|
|
4
|
+
* SDTs are package-backed wrappers, not L08 scope truth. This helper only
|
|
5
|
+
* reports overlap with a scope range so capability and validation surfaces can
|
|
6
|
+
* stay preserve-first until L02/L04 expose richer source/layout refs.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
CanonicalDocument,
|
|
11
|
+
DocumentRootNode,
|
|
12
|
+
SdtNode,
|
|
13
|
+
} from "../../model/canonical-document.ts";
|
|
14
|
+
import type { CanonicalDocumentEnvelope } from "../../core/state/editor-state.ts";
|
|
15
|
+
|
|
16
|
+
import { computeBlockPositions, type ScopePositionRange } from "./position-map.ts";
|
|
17
|
+
import { rangesOverlap } from "./scope-range.ts";
|
|
18
|
+
import type {
|
|
19
|
+
ScopeContentControlEvidence,
|
|
20
|
+
ScopeContentControlEvidenceEntry,
|
|
21
|
+
} from "./semantic-scope-types.ts";
|
|
22
|
+
|
|
23
|
+
function documentRoot(
|
|
24
|
+
document: Pick<CanonicalDocument, "content"> | CanonicalDocumentEnvelope,
|
|
25
|
+
): DocumentRootNode {
|
|
26
|
+
const envelope = document as CanonicalDocumentEnvelope;
|
|
27
|
+
return "content" in envelope
|
|
28
|
+
? (envelope.content as DocumentRootNode)
|
|
29
|
+
: (document as unknown as DocumentRootNode);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function entryForSdt(
|
|
33
|
+
blockIndex: number,
|
|
34
|
+
sdt: SdtNode,
|
|
35
|
+
): ScopeContentControlEvidenceEntry {
|
|
36
|
+
const typePart = sdt.properties.sdtType ?? "unknown";
|
|
37
|
+
return {
|
|
38
|
+
evidenceId: `sdt:${blockIndex}:${typePart}`,
|
|
39
|
+
blockIndex,
|
|
40
|
+
...(sdt.properties.sdtType ? { sdtType: sdt.properties.sdtType } : {}),
|
|
41
|
+
...(sdt.properties.alias ? { alias: sdt.properties.alias } : {}),
|
|
42
|
+
...(sdt.properties.tag ? { tag: sdt.properties.tag } : {}),
|
|
43
|
+
...(sdt.properties.lock ? { lock: sdt.properties.lock } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function findContentControlsIntersectingRange(
|
|
48
|
+
document: Pick<CanonicalDocument, "content"> | CanonicalDocumentEnvelope,
|
|
49
|
+
range: ScopePositionRange | null,
|
|
50
|
+
): readonly ScopeContentControlEvidenceEntry[] {
|
|
51
|
+
if (!range) return Object.freeze([]);
|
|
52
|
+
|
|
53
|
+
const root = documentRoot(document);
|
|
54
|
+
const blockRanges = computeBlockPositions(document);
|
|
55
|
+
const entries: ScopeContentControlEvidenceEntry[] = [];
|
|
56
|
+
|
|
57
|
+
for (const blockRange of blockRanges) {
|
|
58
|
+
const block = root.children[blockRange.blockIndex];
|
|
59
|
+
if (!block || block.type !== "sdt") continue;
|
|
60
|
+
if (!rangesOverlap(range, { from: blockRange.from, to: blockRange.to })) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
entries.push(entryForSdt(blockRange.blockIndex, block));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return Object.freeze(entries);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function deriveScopeContentControlEvidence(
|
|
70
|
+
document: Pick<CanonicalDocument, "content"> | CanonicalDocumentEnvelope,
|
|
71
|
+
range: ScopePositionRange | null,
|
|
72
|
+
): ScopeContentControlEvidence {
|
|
73
|
+
const entries = findContentControlsIntersectingRange(document, range);
|
|
74
|
+
return {
|
|
75
|
+
status: entries.length > 0 ? "present" : "none",
|
|
76
|
+
count: entries.length,
|
|
77
|
+
entries,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -9,10 +9,9 @@
|
|
|
9
9
|
* Issues are metadata records rather than a dedicated overlay section
|
|
10
10
|
* in this slice — matches the Slice-6 plan's "issue store is a new
|
|
11
11
|
* section on the workflow overlay" intent without requiring an
|
|
12
|
-
* overlay-schema minor bump.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* migrates — the metadataId stays stable so callers don't break.
|
|
12
|
+
* overlay-schema minor bump. Layer 06 owns the durable lifecycle substrate for
|
|
13
|
+
* the stable metadataId; L08/L09 still own scope/API shaped resolve/reopen
|
|
14
|
+
* exposure.
|
|
16
15
|
*
|
|
17
16
|
* Scope coverage (coord-06 §13c shipped 2026-04-23): both overlay
|
|
18
17
|
* (workflow) scopes AND derived paragraph / heading / list-item
|
|
@@ -28,9 +27,10 @@ import type {
|
|
|
28
27
|
MetadataWriterRuntime,
|
|
29
28
|
} from "../workflow/metadata-writer.ts";
|
|
30
29
|
import { attachScopeMetadata } from "../workflow/metadata-writer.ts";
|
|
30
|
+
import { AI_ISSUE_METADATA_ID } from "../workflow/ai-issue-lifecycle.ts";
|
|
31
31
|
|
|
32
32
|
/** Stable metadataId for AI-authored issues. */
|
|
33
|
-
export
|
|
33
|
+
export { AI_ISSUE_METADATA_ID };
|
|
34
34
|
|
|
35
35
|
export type IssueSeverity = "info" | "warning" | "error";
|
|
36
36
|
export type IssueStatus = "open" | "resolved";
|