@ingcreators/annot-product-docs 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,268 @@
1
1
  # @ingcreators/annot-product-docs
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b5d52f6: **Annotation palette composes onto the annotated PNG** — Phase 3c
8
+ of `docs/plans/living-spec-authoring-roadmap.md`. The Astro Image
9
+ Service's `renderAnnotatedScreen` now reads the Phase 3a yaml
10
+ `annotations[]` section and bakes the full visual palette
11
+ (rect / circle / arrow / text / callout / freehand / redact /
12
+ focusMask) onto the base PNG, layered underneath the existing
13
+ numbered-badge overlays.
14
+
15
+ ### New public surface — `@ingcreators/annot-product-docs`
16
+
17
+ `buildShapeAnnotationsFromYaml(annotations, boxed, dims) →
18
+ BboxAnnotation[]` maps each Phase 3a `AnnotationSpec` against the
19
+ page's `BoxedEntry[]` (from snapshot YAML or PNG XMP ElementTree)
20
+ and produces `BboxAnnotation` shapes the headless annotator's
21
+ `bboxAnnotationsToSvg` consumes. Per-variant resolution:
22
+ - **`rect`** — `match` / `coversElements[]` / `bbox`. `coversElements`
23
+ unions the per-element bboxes into one.
24
+ - **`circle`** — match-anchored circles centre on the element bbox
25
+ with radius defaulting to half the longer axis; `center` + `radius`
26
+ is the free-coord form.
27
+ - **`arrow`** — endpoints can be `{ match }` (centre-to-centre) or
28
+ `{ point }`.
29
+ - **`text`** — `anchor.position` (above / below / left / right /
30
+ center) offsets a centred / left- / right-anchored label by 8 px
31
+ outside the element bbox.
32
+ - **`callout`** — target = match-resolved or free-coord bbox; `at`
33
+ is the caption position.
34
+ - **`freehand`** — passes through verbatim.
35
+ - **`redact`** — style: `solid` renders as a filled rect (default
36
+ fill `#222222`, no stroke); `fill` / `stroke` overrides honoured.
37
+ - **`focusMask`** — cutout expands by `padding` (match-anchored);
38
+ outer rect collapses to the supplied image dims.
39
+
40
+ Intent mapping mirrors the existing badge path
41
+ (`required → error`, `action → warning`, others pass through).
42
+
43
+ Match resolution failures are silently skipped — the drift
44
+ detector (Phase 3d) surfaces them upstream so the build keeps
45
+ producing a useful PNG even when the snapshot has drifted.
46
+
47
+ ### Behaviour change — `renderAnnotatedScreen`
48
+
49
+ When `<Screen annotations="…">` resolves to a yaml carrying
50
+ `annotations[]`, the renderer composes shapes (underneath) + badges
51
+ (on top) into one SVG fragment via `svgFromBboxAnnotations`. The
52
+ cache key already includes the annotations-yaml source from
53
+ Phase 2b, so edits to the yaml bust the cached PNG without extra
54
+ bookkeeping. Pre-Phase-3 yaml files (no `annotations` key) parse
55
+ - render unchanged.
56
+
57
+ ### Compatibility
58
+
59
+ Additive. Existing callers that only use `overlays[]` see no
60
+ behaviour change. The new `buildShapeAnnotationsFromYaml` export
61
+ is opt-in.
62
+
63
+ - fa712fd: **Annotation palette drift + xlsx coverage (Phase 3d)** — closes
64
+ Phase 3 of `docs/plans/living-spec-authoring-roadmap.md`.
65
+
66
+ ### Drift detector — `yamlAnnotations` opt-in
67
+
68
+ `detectDrift` / `detectDriftFromYaml` / `detectDriftFromElementTree`
69
+ gain an optional `yamlAnnotations: readonly AnnotationSpec[]`
70
+ field. When set, the detector walks the match keys reachable from
71
+ each Phase 3a `AnnotationSpec` (via the new
72
+ `collectMatchKeysFromAnnotation(spec) → MatchKey[]` helper) and
73
+ runs them through the same match-cycle as overlays — emitting
74
+ `removed` / `renamed` / `role-changed` / `duplicated` findings
75
+ with the annotation `id` referenced in the message.
76
+
77
+ Free-coord variants (`bbox`-only rect / `point`-only arrow
78
+ endpoint / `at`-only text / `bbox`-only callout target /
79
+ freehand / `bbox`-only redact / `bbox`-only focusMask cutout)
80
+ contribute zero keys and pass through silently.
81
+
82
+ `annotations[]` IDs are NEVER referenced from `<AnnotCallout for>`
83
+ (overlays[] owns that contract), so no
84
+ `description-missing` / `description-orphan` findings fire for
85
+ this source.
86
+
87
+ ### Excel adapter — yaml-driven rows for migrated screens
88
+
89
+ `@ingcreators/annot-product-docs-xlsx`'s `extractFromParsed`
90
+ gains an optional `annotationsYamlByPath` context map. When a
91
+ `<Screen>` carries `annotations="…"` and the matching yaml is in
92
+ the map, the item-table rows are sourced from the yaml's
93
+ `overlays[]` (each row's body cross-referenced from
94
+ `screen.callouts` by id). `extractMdxFile` loads each
95
+ referenced yaml file from disk automatically — missing files are
96
+ a loud failure on the same "explicit reference, but file gone"
97
+ reasoning the Astro Image Service uses.
98
+
99
+ `annotations[]` entries in the yaml are deliberately NOT
100
+ surfaced as rows. The Astro Image Service composes them onto
101
+ the annotated PNG; the Excel adapter renders the resulting image
102
+ in the spreadsheet's picture column while the items table stays
103
+ scoped to overlays.
104
+
105
+ ### workflow-app dogfood
106
+
107
+ `examples/workflow-app/docs/books/operation-manual/OM-001-login.mdx`
108
+ migrates from inline `<Overlay>` to the
109
+ `<Screen annotations="./OM-001-login.annotations.yaml">` +
110
+ `<AnnotCallout for>` form. The companion yaml ships three
111
+ overlays plus three `annotations[]` entries exercising
112
+ `rect` + `arrow` + `focusMask` — the full Phase 3 palette
113
+ end-to-end through the workflow-app's docs build.
114
+
115
+ ### Compatibility
116
+
117
+ Additive. Existing drift callers see no behaviour change unless
118
+ they opt in to `yamlAnnotations`. Existing xlsx callers see no
119
+ behaviour change unless they migrate a screen to the yaml form;
120
+ inline-`<Overlay>` screens continue to drive rows as before.
121
+
122
+ - f09a6b1: **Annotation yaml `redact.style` accepts `mosaic` / `blur`** —
123
+ Phase 3f of `docs/plans/living-spec-authoring-roadmap.md`
124
+ (Phase 3 follow-up).
125
+
126
+ The Phase 3a parser shipped `redact.style: "solid"` only; mosaic
127
+ / blur were explicitly rejected with a "reserved for follow-up"
128
+ message. Phase 3f widens the enum to all three (`solid` /
129
+ `mosaic` / `blur`) so authoring tools and the Astro Image
130
+ Service can use the values end-to-end.
131
+
132
+ ### Parser behaviour
133
+
134
+ ```yaml
135
+ # Phase 3a: accepted
136
+ annotations:
137
+ - id: redact-1
138
+ kind: redact
139
+ bbox: { x: 0, y: 0, width: 100, height: 30 }
140
+ style: solid
141
+
142
+ # Phase 3f: NEW — both accepted
143
+ annotations:
144
+ - id: redact-2
145
+ kind: redact
146
+ match: { role: textbox, name: Reason }
147
+ style: mosaic
148
+ - id: redact-3
149
+ kind: redact
150
+ bbox: { x: 421, y: 269, width: 438, height: 40 }
151
+ style: blur
152
+ ```
153
+
154
+ Unknown style values still error with an updated message:
155
+ `redact.style must be one of "solid" / "mosaic" / "blur"`.
156
+
157
+ ### Render behaviour (transitional)
158
+
159
+ Between 3f (this PR) and 3g (Astro Image Service raster
160
+ pre-processing), `mosaic` and `blur` redact entries are
161
+ parser-accepted but the Image Service still routes them
162
+ through the SVG-fragment filled-rect path — so they LOOK
163
+ identical to `solid` until 3g lands. 3g wires the raster
164
+ pass that gives `mosaic` / `blur` their distinct visual
165
+ output.
166
+
167
+ ### New public type
168
+
169
+ `RedactAnnotationStyle` (the `"solid" | "mosaic" | "blur"` union)
170
+ is exported from `@ingcreators/annot-product-docs` so callers
171
+ can reference it directly.
172
+
173
+ ### Compatibility
174
+
175
+ Additive within v1. Pre-3f files (no redact entries, or
176
+ `style: solid` only) parse identically. Files authored with
177
+ `style: "mosaic" | "blur"` are rejected by the pre-3f parser
178
+ (loud failure pointing at the unsupported style) — consumers
179
+ on older `@ingcreators/annot-product-docs` upgrade to consume
180
+ the new files.
181
+
182
+ - 0d19345: **Astro Image Service bakes mosaic / blur redacts onto the base
183
+ PNG** — Phase 3g of `docs/plans/living-spec-authoring-roadmap.md`
184
+ (Phase 3 follow-up).
185
+
186
+ When a screen's `annotations[]` yaml carries
187
+ `redact { style: "mosaic" | "blur" }` entries, the renderer now
188
+ calls `burnRedactions` from `@ingcreators/annot-annotator` on
189
+ the base PNG before SVG-fragment composition. `style: solid`
190
+ redacts continue to flow through the existing SVG filled-rect
191
+ path — avoiding an unnecessary PNG round-trip for the common
192
+ solid case.
193
+
194
+ ### New public surface
195
+
196
+ `buildRasterRedactRegionsFromYaml(annotations, boxed) →
197
+ BboxRedactRegion[]` (exported from
198
+ `@ingcreators/annot-product-docs`) walks `annotations[]` for
199
+ raster-style redact entries, resolves each cutout to a bbox,
200
+ and emits regions ready for `burnRedactions`. Match-anchored
201
+ entries whose `match` doesn't resolve are skipped silently —
202
+ the drift detector (Phase 3d) surfaces them upstream so the
203
+ build keeps producing a useful PNG while the snapshot
204
+ catches up.
205
+
206
+ ### `renderAnnotatedScreen` flow
207
+
208
+ ```
209
+ load base PNG bytes
210
+
211
+ read element-tree bboxes
212
+
213
+ walk annotations[] → split into:
214
+ • raster redacts (mosaic / blur) → burnRedactions(base, regions)
215
+ • SVG annotations (rect / circle / arrow / text / callout
216
+ / freehand / solid-redact / focusMask / numberedBadge)
217
+
218
+ compose SVG fragments on top of the (possibly burned) base PNG
219
+
220
+ emit final PNG (flat or editable)
221
+ ```
222
+
223
+ ### `mapRedact` change
224
+
225
+ `mapRedact` in `mdx-annotations.ts` now returns `null` for
226
+ `style: "mosaic" | "blur"` so those entries don't double-bake
227
+ as a filled rect on top of the already-pixelated bitmap. Solid
228
+ redacts continue to produce a `BboxRectAnnotation` for the SVG
229
+ path.
230
+
231
+ ### `hadBoundingBoxes` semantics
232
+
233
+ The flag flips true when raster redacts resolved through bbox
234
+ data, even when no SVG annotations composed on top. This
235
+ matches the flag's intent ("we used the snapshot's bbox data
236
+ to produce a useful render") — a screen with only a mosaic
237
+ redact still benefited from the bbox tour.
238
+
239
+ ### Caching
240
+
241
+ The cache key already includes the annotations-yaml source
242
+ bytes (Phase 2b), so editing a yaml `style: mosaic` → `style:
243
+ blur` value busts the cached PNG without additional
244
+ bookkeeping.
245
+
246
+ ### Compatibility
247
+
248
+ Additive. Existing screens (no `annotations[]`, or
249
+ `annotations[]` with no raster-style redacts) render
250
+ byte-identical. mosaic / blur redacts that were parser-accepted
251
+ in 3f but rendered as solid rects now render as their proper
252
+ raster effect.
253
+
254
+ ### Patch Changes
255
+
256
+ - Updated dependencies [6124d59]
257
+ - Updated dependencies [0c7ac26]
258
+ - Updated dependencies [64dc6e8]
259
+ - Updated dependencies [691bec5]
260
+ - Updated dependencies [9697f27]
261
+ - Updated dependencies [266b05a]
262
+ - @ingcreators/annot-annotator@0.6.0
263
+ - @ingcreators/annot-core@0.3.0
264
+ - @ingcreators/annot-playwright@0.4.1
265
+
3
266
  ## 0.3.0
4
267
 
5
268
  ### Minor Changes
@@ -0,0 +1,291 @@
1
+ import { MatchKey, OverlayIntent } from './types.js';
2
+ /**
3
+ * Current schema version. Per OQ-01 of the roadmap, future v2 / v3
4
+ * bumps go through strict version dispatch (the parser refuses
5
+ * unknown majors); within v1, additive optional fields are allowed
6
+ * without a version bump.
7
+ */
8
+ export declare const ANNOTATIONS_YAML_VERSION: 1;
9
+ /**
10
+ * One numbered-badge overlay entry. Phase 2 supports `numberedBadge`
11
+ * only; Phase 3 of the roadmap extends `OverlayEntry` (and adds a
12
+ * sibling `AnnotationSpec`) for the full annotation palette
13
+ * (`rect` / `arrow` / `text` / `freehand` / `redact` / etc.).
14
+ *
15
+ * The shape mirrors the legacy {@link OverlaySpec} from `./types.ts`
16
+ * minus the inline `body` field — descriptions live in MDX
17
+ * `<AnnotCallout for="id">body</AnnotCallout>` blocks now, not in
18
+ * the yaml.
19
+ */
20
+ export interface OverlayEntry {
21
+ /**
22
+ * Stable identifier targeted by `<AnnotCallout for="id">` in MDX.
23
+ * Author-supplied; the migration CLI (Phase 2d) defaults to
24
+ * `o1` / `o2` / … in `overlays[]` index order.
25
+ */
26
+ id: string;
27
+ /**
28
+ * Discriminator — Phase 2 ships `numberedBadge` only. Adding a
29
+ * new kind here means extending the renderer in `AnnotFigure.astro`
30
+ * AND the drift validator in `./drift.ts`.
31
+ */
32
+ kind: "numberedBadge";
33
+ /** Match key used to locate the element in the page's ElementTree. */
34
+ match: MatchKey;
35
+ /** Optional intent flavour for the rendered callout / border. */
36
+ intent?: OverlayIntent;
37
+ /**
38
+ * Numeric badge label rendered on the image. Author-supplied so
39
+ * the same yaml renders consistent numbering across re-captures
40
+ * even if `overlays[]` order changes. Required by the Astro
41
+ * Image Service today; future kinds may make it optional.
42
+ */
43
+ number: number;
44
+ }
45
+ /**
46
+ * Top-level wire shape for an `.annotations.yaml` file.
47
+ *
48
+ * `overlays[]` carries the numbered-badge entries the docs flow
49
+ * pairs with `<AnnotCallout for="id">` description blocks
50
+ * (Phase 2). `annotations[]` carries the wider visual palette
51
+ * (Phase 3 of the roadmap) — entries are pure visual marking
52
+ * with no MDX description slot; their `id` is self-contained
53
+ * and is NEVER targeted by `<AnnotCallout for>`.
54
+ *
55
+ * Both arrays default to empty when absent. Within v1 the
56
+ * `annotations[]` extension is additive: pre-Phase-3 files
57
+ * (no `annotations` key) keep parsing unchanged.
58
+ *
59
+ * `meta` is an open string map reserved for downstream tooling
60
+ * (book grouping, generator IDs, etc.) — readers must ignore
61
+ * unknown keys.
62
+ */
63
+ export interface AnnotationsFile {
64
+ version: typeof ANNOTATIONS_YAML_VERSION;
65
+ overlays: OverlayEntry[];
66
+ /**
67
+ * Phase 3 of `docs/plans/living-spec-authoring-roadmap.md`.
68
+ * Optional sibling of `overlays[]` carrying the full visual
69
+ * palette (arrows / rects / text labels / callouts / freehand
70
+ * strokes / redact rects / focus masks). Each entry composes
71
+ * onto the annotated PNG but has no MDX `<AnnotCallout>`
72
+ * counterpart.
73
+ */
74
+ annotations?: AnnotationSpec[];
75
+ /** Optional free-form metadata. Readers ignore unknown keys. */
76
+ meta?: Record<string, string>;
77
+ }
78
+ /**
79
+ * Common style fields any annotation kind may carry. Mirrors the
80
+ * `AnnotationStyle` shape in `@ingcreators/annot-annotator`'s DSL
81
+ * so the yaml → `BboxAnnotation` mapper (Phase 3c) flows straight
82
+ * through. Inlined here rather than imported so this Tier A module
83
+ * stays free of the annotator dependency at parse time.
84
+ */
85
+ export interface AnnotationStyleFields {
86
+ /** Semantic colour shorthand. Renderer maps to design-system tokens. */
87
+ intent?: OverlayIntent;
88
+ /** CSS stroke colour override (wins over `intent`-derived default). */
89
+ stroke?: string;
90
+ /** Stroke width in image pixels. */
91
+ strokeWidth?: number;
92
+ /** CSS fill colour override (wins over `intent`-derived default). */
93
+ fill?: string;
94
+ /** CSS text-fill colour override. */
95
+ color?: string;
96
+ }
97
+ /** Axis-aligned bbox in page (image) pixels. */
98
+ export interface AnnotationBBox {
99
+ x: number;
100
+ y: number;
101
+ width: number;
102
+ height: number;
103
+ }
104
+ /** Point in page (image) pixels. */
105
+ export interface AnnotationPoint {
106
+ x: number;
107
+ y: number;
108
+ }
109
+ /**
110
+ * Where a text label sits relative to its anchor element. The
111
+ * renderer picks a sensible offset (image-pixel padding) per
112
+ * position. Default `above`.
113
+ */
114
+ export type TextAnchorPosition = "above" | "below" | "left" | "right" | "center";
115
+ /**
116
+ * Outline (or filled) rect that highlights one element, a group of
117
+ * elements (bbox = union), or a free-coord region.
118
+ *
119
+ * Exactly one of `match` / `coversElements` / `bbox` is required;
120
+ * the parser rejects entries that supply zero or multiple.
121
+ */
122
+ export interface RectAnnotation extends AnnotationStyleFields {
123
+ id: string;
124
+ kind: "rect";
125
+ match?: MatchKey;
126
+ coversElements?: MatchKey[];
127
+ bbox?: AnnotationBBox;
128
+ }
129
+ /**
130
+ * Circle centred on an element (radius derived from the element's
131
+ * bbox half-width) or on a free-coord point.
132
+ */
133
+ export interface CircleAnnotation extends AnnotationStyleFields {
134
+ id: string;
135
+ kind: "circle";
136
+ /** Element to centre the circle on. Mutually exclusive with `center`. */
137
+ match?: MatchKey;
138
+ /** Free-coord centre. Mutually exclusive with `match`. */
139
+ center?: AnnotationPoint;
140
+ /**
141
+ * Radius in image pixels. Required for the `center` form;
142
+ * optional override for the `match` form (defaults to half the
143
+ * element's bbox width).
144
+ */
145
+ radius?: number;
146
+ }
147
+ /** Arrow endpoint — either match-anchored or free-coord. */
148
+ export type ArrowEndpoint = {
149
+ match: MatchKey;
150
+ } | {
151
+ point: AnnotationPoint;
152
+ };
153
+ /** Arrow between two endpoints. */
154
+ export interface ArrowAnnotation extends AnnotationStyleFields {
155
+ id: string;
156
+ kind: "arrow";
157
+ from: ArrowEndpoint;
158
+ to: ArrowEndpoint;
159
+ }
160
+ /**
161
+ * Text label anchored to an element or placed at a free-coord
162
+ * point. Exactly one of `anchor` / `at` is required.
163
+ */
164
+ export interface TextAnnotation extends AnnotationStyleFields {
165
+ id: string;
166
+ kind: "text";
167
+ text: string;
168
+ /** Match-anchored. The renderer offsets per `position`. */
169
+ anchor?: {
170
+ match: MatchKey;
171
+ position?: TextAnchorPosition;
172
+ };
173
+ /** Free-coord placement. */
174
+ at?: AnnotationPoint;
175
+ /** Font size in image pixels. Default `14`. */
176
+ fontSize?: number;
177
+ }
178
+ /** Callout target — either match-anchored or free-coord. */
179
+ export type CalloutTarget = {
180
+ match: MatchKey;
181
+ } | {
182
+ bbox: AnnotationBBox;
183
+ };
184
+ /**
185
+ * Callout = target outline + caption text + arrow from caption to
186
+ * target. The caption sits at `at`; the target highlights at
187
+ * `target` (resolved to a bbox via match or supplied directly).
188
+ */
189
+ export interface CalloutAnnotation extends AnnotationStyleFields {
190
+ id: string;
191
+ kind: "callout";
192
+ text: string;
193
+ target: CalloutTarget;
194
+ /** Caption text position. Required for now (auto-placement is a future enhancement). */
195
+ at: AnnotationPoint;
196
+ }
197
+ /**
198
+ * Free-form path. Always free-coord — UI changes may misalign
199
+ * it; the editor's drift detector intentionally skips it.
200
+ */
201
+ export interface FreehandAnnotation extends AnnotationStyleFields {
202
+ id: string;
203
+ kind: "freehand";
204
+ /** SVG path data — `M` / `L` / `C` / `Q` / `Z` commands. */
205
+ path: string;
206
+ }
207
+ /**
208
+ * Style of a redact rect. `solid` paints an opaque rect over the
209
+ * region; `mosaic` and `blur` are raster transforms applied to
210
+ * the underlying screenshot bitmap before SVG-fragment
211
+ * composition (Phase 3 follow-up — see Astro Image Service for
212
+ * the rendering path).
213
+ */
214
+ export type RedactAnnotationStyle = "solid" | "mosaic" | "blur";
215
+ /**
216
+ * Opaque or scrambled rect obscuring content. `solid` renders as
217
+ * a filled rect via the SVG-fragment path; `mosaic` and `blur`
218
+ * trigger a raster pre-processing pass in the Astro Image Service
219
+ * (Phase 3 follow-up — Phase 3a–3d shipped `solid` only).
220
+ */
221
+ export interface RedactAnnotation extends AnnotationStyleFields {
222
+ id: string;
223
+ kind: "redact";
224
+ match?: MatchKey;
225
+ bbox?: AnnotationBBox;
226
+ /**
227
+ * Defaults to `solid` at render time when omitted. Phase 3 follow-up
228
+ * (3f) widened this from the original `"solid"`-only to also
229
+ * accept `"mosaic"` and `"blur"` — both routed through
230
+ * `burnRedactions` from `@ingcreators/annot-annotator`.
231
+ */
232
+ style?: RedactAnnotationStyle;
233
+ }
234
+ /** Focus-mask cutout — element-anchored (with optional padding) or free-coord bbox. */
235
+ export type FocusMaskCutout = {
236
+ match: MatchKey;
237
+ padding?: number;
238
+ } | {
239
+ bbox: AnnotationBBox;
240
+ };
241
+ /**
242
+ * Darken everything EXCEPT the cutout region. The cutout draws
243
+ * crisp; everything outside is dimmed by `dimColor`
244
+ * (default `rgba(0,0,0,0.5)`).
245
+ */
246
+ export interface FocusMaskAnnotation extends AnnotationStyleFields {
247
+ id: string;
248
+ kind: "focusMask";
249
+ cutout: FocusMaskCutout;
250
+ /** CSS colour for the dim layer. Default `rgba(0,0,0,0.5)`. */
251
+ dimColor?: string;
252
+ }
253
+ /**
254
+ * Discriminated union across every annotation kind Phase 3
255
+ * supports. Parser dispatches on `kind`; serializer round-trips
256
+ * to YAML and back to a byte-equivalent object.
257
+ */
258
+ export type AnnotationSpec = RectAnnotation | CircleAnnotation | ArrowAnnotation | TextAnnotation | CalloutAnnotation | FreehandAnnotation | RedactAnnotation | FocusMaskAnnotation;
259
+ /** The `kind` literal type. */
260
+ export type AnnotationKind = AnnotationSpec["kind"];
261
+ /** Set of every supported `kind`. Reused by the parser + drift detector. */
262
+ export declare const ANNOTATION_KINDS: readonly AnnotationKind[];
263
+ /**
264
+ * Error thrown when a YAML payload cannot be parsed into the
265
+ * documented schema. Carries the offending source so callers can
266
+ * surface line / column context (the CLI prefixes path + heading).
267
+ */
268
+ export declare class AnnotationsYamlError extends Error {
269
+ readonly source?: string | undefined;
270
+ constructor(message: string, source?: string | undefined);
271
+ }
272
+ /**
273
+ * Parse a YAML string into an `AnnotationsFile`. Throws
274
+ * {@link AnnotationsYamlError} on shape violations: missing
275
+ * `version`, unsupported major, missing required `id` / `kind` /
276
+ * `match` / `number` on an overlay entry.
277
+ *
278
+ * The parser is permissive about optional fields: unknown keys at
279
+ * any level are dropped silently (forward compat within a major).
280
+ */
281
+ export declare function parseAnnotationsYaml(source: string): AnnotationsFile;
282
+ /**
283
+ * Serialize an `AnnotationsFile` back to YAML. Output is
284
+ * deterministic (`version` → `overlays` → `meta`), suitable for
285
+ * round-trip + git-diff use.
286
+ *
287
+ * The serializer rejects entries that wouldn't round-trip through
288
+ * `parseAnnotationsYaml` — kind is checked at the type level, but
289
+ * missing `id` / `match` / `number` at runtime throws.
290
+ */
291
+ export declare function serializeAnnotationsYaml(file: AnnotationsFile): string;