@xtrable-ltd/nanoesis 0.1.9 → 0.1.11

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 (32) hide show
  1. package/dist/adapter-azure-blob.d.ts +7 -1
  2. package/dist/adapter-azure-blob.js +2 -2
  3. package/dist/{chunk-J6VYOB47.js → chunk-XO3CT6GL.js} +1699 -1167
  4. package/dist/editor-api.d.ts +39 -2
  5. package/dist/editor-api.js +396 -6
  6. package/dist/index.d.ts +491 -222
  7. package/dist/index.js +25 -1
  8. package/editor/assets/MigrationsPane-BAHPPSXP.css +1 -0
  9. package/editor/assets/MigrationsPane-BYGqWBAA.js +4 -0
  10. package/editor/assets/{TemplatesPane-CHzfB00-.js → TemplatesPane-B5hn_v0Z.js} +208 -202
  11. package/editor/assets/{TemplatesPane-B4_sg2u5.css → TemplatesPane-D0gGehUt.css} +1 -1
  12. package/editor/assets/{cssMode-BahdJh1A.js → cssMode-BbIf5k6I.js} +1 -1
  13. package/editor/assets/{freemarker2-2FC3twUE.js → freemarker2-DoW0pSYV.js} +1 -1
  14. package/editor/assets/{handlebars-pMjPHNx1.js → handlebars-DLlET-qc.js} +1 -1
  15. package/editor/assets/{html-KTToTG0n.js → html-4khbqrhe.js} +1 -1
  16. package/editor/assets/{htmlMode-ufik94dZ.js → htmlMode-DblHkZ-k.js} +1 -1
  17. package/editor/assets/index-CkESQLMV.css +7 -0
  18. package/editor/assets/index-Do1drqEQ.js +138 -0
  19. package/editor/assets/{javascript-CD4kAZXr.js → javascript-CgPO2Hmj.js} +1 -1
  20. package/editor/assets/{jsonMode-ClHucayn.js → jsonMode-BrWh2436.js} +1 -1
  21. package/editor/assets/{liquid-B-uYib60.js → liquid-BsQJXwPT.js} +1 -1
  22. package/editor/assets/{mdx-BOc9oMkZ.js → mdx-AO8t67gx.js} +1 -1
  23. package/editor/assets/{python-BipLFHGs.js → python-3w4sZj5c.js} +1 -1
  24. package/editor/assets/{razor-C0di_gwM.js → razor-BFsvo06w.js} +1 -1
  25. package/editor/assets/{tsMode-B7fenrcD.js → tsMode-QrC4ERjp.js} +1 -1
  26. package/editor/assets/{typescript-CDg7c2A-.js → typescript-BXJ3QLad.js} +1 -1
  27. package/editor/assets/{xml-DTAdn5Pw.js → xml-CxKYn1FP.js} +1 -1
  28. package/editor/assets/{yaml-B9-OjY0Z.js → yaml-BmWLvF7Q.js} +1 -1
  29. package/editor/index.html +2 -2
  30. package/package.json +1 -1
  31. package/editor/assets/index-BsRGVHEP.css +0 -7
  32. package/editor/assets/index-CPKtfzWD.js +0 -134
package/dist/index.d.ts CHANGED
@@ -152,7 +152,12 @@ interface DirEntry {
152
152
  readonly kind: EntryKind;
153
153
  }
154
154
  interface ContentSource {
155
- /** Immediate children of a directory. */
155
+ /**
156
+ * Immediate children of a directory, sorted by `name` ascending. The sort is part
157
+ * of the port contract (CLAUDE §2: determinism) — every implementation must return
158
+ * a stable order so downstream Map/Set/loop iteration over the result produces
159
+ * byte-identical output across runs.
160
+ */
156
161
  list(dir: string): Promise<readonly DirEntry[]>;
157
162
  /** Read a UTF-8 text file; rejects if it does not exist. */
158
163
  readText(path: string): Promise<string>;
@@ -175,164 +180,6 @@ declare class InMemoryContentSource implements ContentSource {
175
180
  list(dir: string): Promise<readonly DirEntry[]>;
176
181
  }
177
182
 
178
- /**
179
- * The outcome of a {@link WorkingStore.rename}. Clobbering an existing destination, or
180
- * renaming a path that does not exist, are *expected* outcomes (a user renames to a name
181
- * already in use), so they are returned as data, not thrown (CLAUDE §2): the host maps
182
- * them to 409/404.
183
- */
184
- type RenameResult = {
185
- readonly ok: true;
186
- } | {
187
- readonly ok: false;
188
- readonly reason: 'exists' | 'missing';
189
- };
190
- /**
191
- * The editor's working store (DESIGN §11c): a read {@link ContentSource} for
192
- * compile/validate, plus the write/delete/rename the editor content API needs. The
193
- * editor API depends on this port, never a concrete store, so the index-backed
194
- * {@link IndexedStore} (over an adopter's get/put/delete) and the blob adapter are
195
- * interchangeable behind it.
196
- */
197
- interface WorkingStore extends ContentSource {
198
- /** Create or overwrite `path` with raw bytes (binary-correct). */
199
- write(path: string, contents: Uint8Array): Promise<void>;
200
- /** Delete a file, or a whole directory subtree; a missing path is a no-op. */
201
- delete(path: string): Promise<void>;
202
- /** Move a file or subtree; refuses to clobber, or to rename a missing path. */
203
- rename(from: string, to: string): Promise<RenameResult>;
204
- }
205
-
206
- /**
207
- * The content index (DESIGN §11d): the sorted set of every key in the working store,
208
- * the directory listing a flat blob store cannot give cheaply, lifted into one object
209
- * we own. Enumeration (the editor tree, compile) reads this, so the adopter's store
210
- * stays get/put/delete with no `list`. Persisted under a reserved key with a fixed-size
211
- * backup ring for integrity.
212
- */
213
- interface ContentIndex {
214
- /** Monotonic, bumped on every save; orders the backup ring during recovery. */
215
- readonly version: number;
216
- /** Every key that exists, sorted and de-duplicated (deterministic, CLAUDE §2). */
217
- readonly keys: readonly string[];
218
- /** Checksum over version + keys, so a corrupt stored index is caught on read. */
219
- readonly checksum: string;
220
- }
221
- /** Reserved key prefix for the index and its backups; excluded from enumeration. */
222
- declare const RESERVED_PREFIX = ".nanoesis/";
223
- /** The empty index of a fresh store: version 0, no keys. */
224
- declare function emptyIndex(): ContentIndex;
225
- /**
226
- * Load the index, recovering through the backup ring if the live copy is missing or
227
- * corrupt (DESIGN §11d): the highest valid version among the ring slots wins. Returns
228
- * the empty index when nothing valid is found, a fresh store, or the accepted residual
229
- * case where the live index and every backup are lost (the files still exist by key,
230
- * but cannot be enumerated until something rewrites the index).
231
- */
232
- declare function loadIndex(store: BlobStore): Promise<ContentIndex>;
233
- /**
234
- * Write a new index whose keys are `nextKeys`, backing up the one it replaces first
235
- * (DESIGN §11d). The previous index goes into its ring slot (`version % ring`, oldest
236
- * overwritten), then the new index is written to the live key, a constant two writes
237
- * per save regardless of ring size. Returns the new index (the caller's next `prev`).
238
- */
239
- declare function saveIndex(store: BlobStore, prev: ContentIndex, nextKeys: readonly string[]): Promise<ContentIndex>;
240
- /** What a {@link reconcileIndex} did, for a maintenance UI/CLI and the startup signal. */
241
- interface ReconcileResult {
242
- /** The index after reconciling (the prior one unchanged when nothing differed). */
243
- readonly index: ContentIndex;
244
- /** Keys now in the index that the prior index lacked (orphaned blobs, recovered). */
245
- readonly added: readonly string[];
246
- /** Keys the prior index held that no longer exist in the store (stale entries dropped). */
247
- readonly removed: readonly string[];
248
- }
249
- /**
250
- * Rebuild the index from the store's *actual* keys (DESIGN §11d): the safety net for a
251
- * store that got files by a path that bypassed the index, where the files are present
252
- * by key but unenumerable. The engine cannot list a {@link BlobStore} (none is required
253
- * to, §11c), so the caller supplies the real key set, an adapter that *can* enumerate
254
- * (e.g. `BlobContainer.list`) provides it; the rebuild stays pure index logic here.
255
- *
256
- * The reserved namespace is never indexed (the index is not its own content). When the
257
- * resulting key set matches the existing index this is a no-op, no write, no version
258
- * bump, so reconciling a healthy store is cheap and idempotent.
259
- */
260
- declare function reconcileIndex(store: BlobStore, actualKeys: readonly string[]): Promise<ReconcileResult>;
261
-
262
- /**
263
- * A {@link ContentSource} backed by the content index (DESIGN §11d) over a
264
- * {@link BlobStore}: enumeration (`list`/`exists`) is synthesised from the index's key
265
- * set, reads go straight to `get`. This is the working store the editor and compile run
266
- * against once an adopter provides only get/put/delete, every existing `list` caller is
267
- * unchanged because it still sees a `ContentSource`.
268
- *
269
- * Mutations (`write`/`delete`/`rename`) write the file(s) first, then the index
270
- * (content-first, §11d), keeping the in-memory copy in step so reads on this instance
271
- * reflect the change at once. The index is only rewritten when the key *set* changes, an
272
- * overwrite of an existing key is a single `put`.
273
- *
274
- * Construction does no I/O: the index loads (and recovers through the backup ring, §11d)
275
- * lazily on the first enumeration or mutation, so a host can wire the store synchronously.
276
- *
277
- * The prefix-synthesis below mirrors {@link InMemoryContentSource} exactly (a cross-check
278
- * test pins them together); the two are interchangeable implementations of the port.
279
- */
280
- declare class IndexedStore implements WorkingStore {
281
- private readonly store;
282
- private index;
283
- private loading;
284
- /**
285
- * Per-instance mutex (DESIGN §11d): every mutation (`write`/`delete`/`rename`/`reconcile`)
286
- * runs through {@link serializeMutation}, which chains onto the previous mutation's
287
- * completion. Without it, two concurrent mutations both read the cached `this.index`,
288
- * each compute their "next" key set from that stale snapshot, and the second
289
- * `saveIndex` clobbers the first — the file writes land in blob, but the index keeps
290
- * stale references or loses fresh ones (the "I deleted it and it's still there" or
291
- * "I added it and it didn't appear" bugs surfaced dogfooding the marketing site,
292
- * 2026-05-28). Reads (`list`/`exists`/`readBytes`) are *not* serialised; an
293
- * in-flight mutation simply means a reader sees the pre-mutation index, eventually
294
- * consistent and safe. Crashes inside `work()` release the lock so a single failure
295
- * does not deadlock subsequent operations.
296
- */
297
- private mutationLock;
298
- constructor(store: BlobStore);
299
- /** The index, loaded once on first need and cached (mutations replace the cached copy). */
300
- private loaded;
301
- private serializeMutation;
302
- list(dir: string): Promise<readonly DirEntry[]>;
303
- readText(path: string): Promise<string>;
304
- readBytes(path: string): Promise<Uint8Array>;
305
- exists(path: string): Promise<boolean>;
306
- /**
307
- * Create or overwrite `key`. The index is rewritten only when `key` is new (an
308
- * overwrite leaves the key set unchanged, so editing an item is a single `put`).
309
- */
310
- write(key: string, bytes: Uint8Array): Promise<void>;
311
- /**
312
- * Delete a file, or a whole directory subtree (every key under `key/`). Idempotent: a
313
- * path the index does not know is still deleted from the store (clearing an orphan),
314
- * and deleting nothing is a no-op.
315
- */
316
- delete(key: string): Promise<void>;
317
- /**
318
- * Move/rename a file, or a whole directory subtree (every key under `from/` is remapped
319
- * under `to/`). Clobbering an existing destination, or renaming a missing path, are
320
- * returned as data (`ok: false`), not thrown (CLAUDE §2), the same contract the host's
321
- * `/api/rename` enforces. (Mutating the reserved namespace is a programmer error and
322
- * still throws.)
323
- */
324
- rename(from: string, to: string): Promise<RenameResult>;
325
- /**
326
- * Rebuild this store's index from the *actual* keys the underlying store holds (DESIGN
327
- * §11d), recovering files that arrived by a path that bypassed the index. A
328
- * {@link BlobStore} cannot enumerate itself, so the caller supplies the real key set
329
- * from an adapter that can (e.g. `BlobContainer.list`). Unlike calling
330
- * {@link reconcileIndex} on a fresh store, this also refreshes the cached in-memory
331
- * index, so this live instance sees the recovered files immediately.
332
- */
333
- reconcile(actualKeys: readonly string[]): Promise<ReconcileResult>;
334
- }
335
-
336
183
  /**
337
184
  * The authors byline (DESIGN §6.11). An `authors` field stores an ordered list of
338
185
  * author refs; the compiler renders them as one grammatical line. Everything here
@@ -610,6 +457,384 @@ interface CompileInput {
610
457
  */
611
458
  declare function compileTemplate(input: CompileInput): string;
612
459
 
460
+ /**
461
+ * The field-type registry (DESIGN §6.7). Field types and their rules are defined
462
+ * *once* here and shared by the compiler, the editor's form generator, and (later)
463
+ * Monaco's IntelliSense. This is the OCP extension point (CLAUDE.md §3): adding a
464
+ * field type means adding an entry here, never editing a switch in the compiler or
465
+ * the inference cascade.
466
+ */
467
+ type FieldType = 'image' | 'file' | 'url' | 'email' | 'phone' | 'date' | 'time' | 'code' | 'richtext' | 'authors' | 'text' | 'shorttext';
468
+ /** How a resolved value is placed into output, the compiler reads this, never the type name. */
469
+ type ValueKind = 'text' | 'html' | 'url' | 'asset' | 'authors';
470
+ interface FieldTypeDef {
471
+ readonly type: FieldType;
472
+ readonly valueKind: ValueKind;
473
+ /** Default editor control hint, consumed by the form generator (DESIGN §7). */
474
+ readonly control: string;
475
+ readonly multiline: boolean;
476
+ }
477
+ declare const FIELD_TYPES: Readonly<Record<FieldType, FieldTypeDef>>;
478
+ declare function isFieldType(value: string): value is FieldType;
479
+ declare function valueKindOf(type: FieldType): ValueKind;
480
+
481
+ /**
482
+ * Derive the editor's form from a template, "the template is the schema"
483
+ * (DESIGN §5.5/§6). Walking the same parse the compiler uses, each page-scope
484
+ * token becomes one field whose control is inferred from where it sits, deduped by
485
+ * name and labelled. This is the single source of truth the editor's form
486
+ * generator and the compiler share (DESIGN §6.7).
487
+ *
488
+ * Inference is **component-aware**: when a component is used (`<doc file="{x}">`),
489
+ * the bound field's type comes from how that prop is used *inside* the component,
490
+ * not from the attribute's position on the usage. A component's prop types are
491
+ * simply the field types of its own body, so the same derivation resolves them,
492
+ * recursively, through nested components, with a cycle guard.
493
+ */
494
+ interface DerivedField {
495
+ readonly name: string;
496
+ readonly type: FieldType;
497
+ readonly label: string;
498
+ readonly required: boolean;
499
+ readonly multiline: boolean;
500
+ readonly help?: string;
501
+ /** Minimum character length (`data-minlength`); the gate warns when shorter. */
502
+ readonly minLength?: number;
503
+ /** Maximum character length (`data-maxlength`); the gate warns when longer. */
504
+ readonly maxLength?: number;
505
+ /** A curated multi-reference (a `data-each` loop field). */
506
+ readonly multiple?: boolean;
507
+ /** Collection the reference picker is scoped to (`data-pick-from`). */
508
+ readonly pickFrom?: string;
509
+ }
510
+ /** Author-declared length bounds on a field value (`data-minlength`/`data-maxlength`). */
511
+ interface LengthConstraints {
512
+ readonly minLength?: number;
513
+ readonly maxLength?: number;
514
+ }
515
+ declare function deriveFields(template: string, components?: ComponentMap): DerivedField[];
516
+
517
+ /**
518
+ * Stamping decisions (PROPOSAL-template-versioning §4.1, PROPOSAL-llm-guardrails §4).
519
+ * `detectStamp` is pure — given the old and new template sources, it decides whether a
520
+ * destructive change is taking place and reports the schema delta (added / removed
521
+ * fields, plus per-token type changes).
522
+ *
523
+ * Two destructive shapes (PROPOSAL-llm-guardrails §1, both share the same recovery
524
+ * story — auto-stamp a snapshot, flag for migration):
525
+ *
526
+ * 1. **Token-set asymmetric.** A token removed or renamed. The token *doesn't exist*
527
+ * in the new schema, so content authored against it has nowhere to render.
528
+ * 2. **Token retained, type changed destructively.** The token *still exists*, but
529
+ * its inferred type can't losslessly render data authored under the old type
530
+ * (`richtext → shorttext` silently escapes HTML; `shorttext → image` reinterprets
531
+ * free text as a path). The §4 rule in {@link isDestructiveTypeChange} encodes
532
+ * which transitions are destructive vs widening.
533
+ *
534
+ * Both flow through `IndexedStore.write`'s auto-stamp path identically — the editor
535
+ * UI and MCP both see the same recovery affordance, regardless of which destructive
536
+ * shape triggered it.
537
+ */
538
+ type TemplateKind = 'template' | 'component';
539
+ /** A field reference (name + inferred type) in the schema delta returned by `computeSchemaDelta`. */
540
+ interface SchemaFieldRef {
541
+ readonly name: string;
542
+ readonly type: FieldType;
543
+ }
544
+ /** A type change on a token retained across the edit (PROPOSAL-llm-guardrails §4-§5). */
545
+ interface TypeChange {
546
+ readonly name: string;
547
+ readonly from: FieldType;
548
+ readonly to: FieldType;
549
+ /** True when the change can't losslessly render data authored under `from`. */
550
+ readonly destructive: boolean;
551
+ }
552
+ /**
553
+ * Structured "what changed" report (PROPOSAL-llm-guardrails §5). Returned by
554
+ * `IndexedStore.write` for template/component writes so callers (MCP, editor UI)
555
+ * can react without re-deriving themselves. Empty arrays everywhere when an edit
556
+ * changes only whitespace, comments, or non-token markup.
557
+ */
558
+ interface SchemaDelta {
559
+ readonly added: readonly SchemaFieldRef[];
560
+ readonly removed: readonly SchemaFieldRef[];
561
+ readonly typeChanged: readonly TypeChange[];
562
+ }
563
+ /** What `detectStamp` learned from comparing two template sources. */
564
+ interface StampDecision {
565
+ readonly destructive: boolean;
566
+ /** Tokens present in `oldSource` but absent in `newSource`, sorted for stability. */
567
+ readonly removedTokens: readonly string[];
568
+ /** Tokens present in `newSource` but absent in `oldSource`, sorted for stability. */
569
+ readonly addedTokens: readonly string[];
570
+ /** Tokens retained but whose inferred type changed (PROPOSAL-llm-guardrails §1). */
571
+ readonly typeChanged: readonly TypeChange[];
572
+ }
573
+ /** The record `stampSnapshot` returns (and that the write path surfaces as `stamped`). */
574
+ interface StampRecord {
575
+ /** The base template/component name (no `@v<N>` suffix). */
576
+ readonly name: string;
577
+ /** The integer version slot the snapshot occupies. */
578
+ readonly version: number;
579
+ /** The full path the snapshot was written to. */
580
+ readonly snapshotPath: string;
581
+ }
582
+ /**
583
+ * Whether a field's type change from `from` to `to` can't losslessly render content
584
+ * authored against `from`. Drives both auto-stamp (destructive triggers a snapshot)
585
+ * and the validation gate's `content.type-drift` warning per-item.
586
+ *
587
+ * The rule (PROPOSAL-llm-guardrails §4) reduces to:
588
+ * - `anything → richtext` is safe (HTML escapes text fine).
589
+ * - `richtext → anything else` is destructive (HTML becomes escaped text).
590
+ * - Free-text → strict date/time is destructive (ISO required, free text won't parse).
591
+ * - `date ↔ time` is destructive (both ISO but different shapes; values don't transfer).
592
+ * - Same `valueKind` otherwise is non-destructive (text ↔ text, asset ↔ asset).
593
+ * - Cross-`valueKind` into text is non-destructive (text representation works).
594
+ * - Everything else cross-kind is destructive (text → asset/url/authors; asset ↔ url; …).
595
+ */
596
+ declare function isDestructiveTypeChange(from: FieldType, to: FieldType): boolean;
597
+ /**
598
+ * Compute the schema delta between two field lists. The richer counterpart to the
599
+ * token-name diff in {@link detectStamp} — used by `IndexedStore.write` to surface
600
+ * `schemaDelta` (PROPOSAL-llm-guardrails §5) without re-deriving on the caller side.
601
+ * Pure; component-aware via `deriveFields`.
602
+ */
603
+ declare function computeSchemaDelta(oldFields: readonly DerivedField[], newFields: readonly DerivedField[]): SchemaDelta;
604
+ /**
605
+ * Decide whether the change from `oldSource` to `newSource` is destructive, and report
606
+ * the schema diff (added / removed / typeChanged). Pure — no I/O. The field-name +
607
+ * type set is derived via the same `deriveFields` the editor's form generator uses
608
+ * (so the "schema" the decision is taken against is identical to what the form shows).
609
+ * Component-aware: fields bound to component props are categorised by how that
610
+ * component uses them internally, matching the compiler's resolution.
611
+ */
612
+ declare function detectStamp(oldSource: string, newSource: string, components?: ComponentMap): StampDecision;
613
+
614
+ /**
615
+ * The outcome of a {@link WorkingStore.rename}. Clobbering an existing destination, or
616
+ * renaming a path that does not exist, are *expected* outcomes (a user renames to a name
617
+ * already in use), so they are returned as data, not thrown (CLAUDE §2): the host maps
618
+ * them to 409/404. The third case — refusing to rename into or out of the reserved
619
+ * template-version namespace (`@v<N>` suffix, PROPOSAL §3) — is also returned as data,
620
+ * not thrown, so the editor and MCP surface a tidy error to the user rather than a 500.
621
+ */
622
+ type RenameResult = {
623
+ readonly ok: true;
624
+ } | {
625
+ readonly ok: false;
626
+ readonly reason: 'exists' | 'missing' | 'reserved-version';
627
+ };
628
+ /**
629
+ * Outcome of a {@link WorkingStore.write}. Returned as data so a caller that cares can
630
+ * surface the stamp info to the user (the `/api/write` route attaches `stamped` to its
631
+ * response; MCP's `write_file` passes it through), while a caller that does not care
632
+ * can ignore the return value entirely (per JavaScript's discard semantics). For
633
+ * non-template writes and for non-destructive template writes, `stamped` is absent.
634
+ */
635
+ interface WriteResult {
636
+ /** Snapshot record when a destructive template/component write triggered auto-stamp. */
637
+ readonly stamped?: StampRecord;
638
+ /**
639
+ * True when the destructive write succeeded but the snapshot copy that should have
640
+ * preserved the old bytes failed. The new current is in place (site stays
641
+ * consistent); the snapshot's old bytes are not preserved. Surfaced as a Health
642
+ * warning (`templates.stamp-incomplete`) so the migration-UX left-pane render
643
+ * is known to be unavailable for items affected by this particular stamp.
644
+ */
645
+ readonly stampIncomplete?: boolean;
646
+ /**
647
+ * The schema diff between the old and new bytes for template/component writes
648
+ * (PROPOSAL-llm-guardrails §5). Present whenever the target is a template or
649
+ * component and there was a prior version; undefined for content writes, public
650
+ * files, and brand-new templates. Carries `added`/`removed` (with types) and
651
+ * `typeChanged` (with per-change `destructive` flag). MCP callers consume this to
652
+ * react to schema impact without re-deriving; the editor surfaces a summary in the
653
+ * stamp banner.
654
+ */
655
+ readonly schemaDelta?: SchemaDelta;
656
+ }
657
+ /**
658
+ * The editor's working store (DESIGN §11c): a read {@link ContentSource} for
659
+ * compile/validate, plus the write/delete/rename the editor content API needs. The
660
+ * editor API depends on this port, never a concrete store, so the index-backed
661
+ * {@link IndexedStore} (over an adopter's get/put/delete) and the blob adapter are
662
+ * interchangeable behind it.
663
+ */
664
+ interface WorkingStore extends ContentSource {
665
+ /**
666
+ * Create or overwrite `path` with raw bytes (binary-correct). Returns a
667
+ * {@link WriteResult}; callers that do not care about stamp info can ignore it.
668
+ * Destructive writes to `templates/*.html` / `components/*.html` auto-stamp a
669
+ * snapshot of the prior bytes before the new bytes land (PROPOSAL §4.1).
670
+ */
671
+ write(path: string, contents: Uint8Array): Promise<WriteResult>;
672
+ /** Delete a file, or a whole directory subtree; a missing path is a no-op. */
673
+ delete(path: string): Promise<void>;
674
+ /** Move a file or subtree; refuses to clobber, to rename a missing path, or to
675
+ * rename into or out of the reserved template-version namespace (`@v<N>`). */
676
+ rename(from: string, to: string): Promise<RenameResult>;
677
+ /**
678
+ * Manually stamp a snapshot of the current `<kind>/<name>.html` to the next
679
+ * `<name>@v<N+1>.html` slot (PROPOSAL §4.1 + §6, the manual "Stamp version" action).
680
+ * Used for the additive-but-want-a-clean-break case the auto-stamp path does not
681
+ * trigger. Throws if the current file does not exist or `name` is already
682
+ * versioned. Distinguished from `write` so the store can bypass its own
683
+ * reserved-path refusal — snapshots are immutable to user-initiated `write`s but
684
+ * the engine's stamp pathway needs to create them.
685
+ */
686
+ stamp(name: string, kind: TemplateKind): Promise<StampRecord>;
687
+ }
688
+
689
+ /**
690
+ * The content index (DESIGN §11d): the sorted set of every key in the working store,
691
+ * the directory listing a flat blob store cannot give cheaply, lifted into one object
692
+ * we own. Enumeration (the editor tree, compile) reads this, so the adopter's store
693
+ * stays get/put/delete with no `list`. Persisted under a reserved key with a fixed-size
694
+ * backup ring for integrity.
695
+ */
696
+ interface ContentIndex {
697
+ /** Monotonic, bumped on every save; orders the backup ring during recovery. */
698
+ readonly version: number;
699
+ /** Every key that exists, sorted and de-duplicated (deterministic, CLAUDE §2). */
700
+ readonly keys: readonly string[];
701
+ /** Checksum over version + keys, so a corrupt stored index is caught on read. */
702
+ readonly checksum: string;
703
+ }
704
+ /** Reserved key prefix for the index and its backups; excluded from enumeration. */
705
+ declare const RESERVED_PREFIX = ".nanoesis/";
706
+ /** The empty index of a fresh store: version 0, no keys. */
707
+ declare function emptyIndex(): ContentIndex;
708
+ /**
709
+ * Load the index, recovering through the backup ring if the live copy is missing or
710
+ * corrupt (DESIGN §11d): the highest valid version among the ring slots wins. Returns
711
+ * the empty index when nothing valid is found, a fresh store, or the accepted residual
712
+ * case where the live index and every backup are lost (the files still exist by key,
713
+ * but cannot be enumerated until something rewrites the index).
714
+ */
715
+ declare function loadIndex(store: BlobStore): Promise<ContentIndex>;
716
+ /**
717
+ * Write a new index whose keys are `nextKeys`, backing up the one it replaces first
718
+ * (DESIGN §11d). The previous index goes into its ring slot (`version % ring`, oldest
719
+ * overwritten), then the new index is written to the live key, a constant two writes
720
+ * per save regardless of ring size. Returns the new index (the caller's next `prev`).
721
+ */
722
+ declare function saveIndex(store: BlobStore, prev: ContentIndex, nextKeys: readonly string[]): Promise<ContentIndex>;
723
+ /** What a {@link reconcileIndex} did, for a maintenance UI/CLI and the startup signal. */
724
+ interface ReconcileResult {
725
+ /** The index after reconciling (the prior one unchanged when nothing differed). */
726
+ readonly index: ContentIndex;
727
+ /** Keys now in the index that the prior index lacked (orphaned blobs, recovered). */
728
+ readonly added: readonly string[];
729
+ /** Keys the prior index held that no longer exist in the store (stale entries dropped). */
730
+ readonly removed: readonly string[];
731
+ }
732
+ /**
733
+ * Rebuild the index from the store's *actual* keys (DESIGN §11d): the safety net for a
734
+ * store that got files by a path that bypassed the index, where the files are present
735
+ * by key but unenumerable. The engine cannot list a {@link BlobStore} (none is required
736
+ * to, §11c), so the caller supplies the real key set, an adapter that *can* enumerate
737
+ * (e.g. `BlobContainer.list`) provides it; the rebuild stays pure index logic here.
738
+ *
739
+ * The reserved namespace is never indexed (the index is not its own content). When the
740
+ * resulting key set matches the existing index this is a no-op, no write, no version
741
+ * bump, so reconciling a healthy store is cheap and idempotent.
742
+ */
743
+ declare function reconcileIndex(store: BlobStore, actualKeys: readonly string[]): Promise<ReconcileResult>;
744
+
745
+ /**
746
+ * A {@link ContentSource} backed by the content index (DESIGN §11d) over a
747
+ * {@link BlobStore}: enumeration (`list`/`exists`) is synthesised from the index's key
748
+ * set, reads go straight to `get`. This is the working store the editor and compile run
749
+ * against once an adopter provides only get/put/delete, every existing `list` caller is
750
+ * unchanged because it still sees a `ContentSource`.
751
+ *
752
+ * Mutations (`write`/`delete`/`rename`) write the file(s) first, then the index
753
+ * (content-first, §11d), keeping the in-memory copy in step so reads on this instance
754
+ * reflect the change at once. The index is only rewritten when the key *set* changes, an
755
+ * overwrite of an existing key is a single `put`.
756
+ *
757
+ * Construction does no I/O: the index loads (and recovers through the backup ring, §11d)
758
+ * lazily on the first enumeration or mutation, so a host can wire the store synchronously.
759
+ *
760
+ * The prefix-synthesis below mirrors {@link InMemoryContentSource} exactly (a cross-check
761
+ * test pins them together); the two are interchangeable implementations of the port.
762
+ */
763
+ declare class IndexedStore implements WorkingStore {
764
+ private readonly store;
765
+ private index;
766
+ private loading;
767
+ /**
768
+ * Per-instance mutex (DESIGN §11d): every mutation (`write`/`delete`/`rename`/`reconcile`)
769
+ * runs through {@link serializeMutation}, which chains onto the previous mutation's
770
+ * completion. Without it, two concurrent mutations both read the cached `this.index`,
771
+ * each compute their "next" key set from that stale snapshot, and the second
772
+ * `saveIndex` clobbers the first — the file writes land in blob, but the index keeps
773
+ * stale references or loses fresh ones (the "I deleted it and it's still there" or
774
+ * "I added it and it didn't appear" bugs surfaced dogfooding the marketing site,
775
+ * 2026-05-28). Reads (`list`/`exists`/`readBytes`) are *not* serialised; an
776
+ * in-flight mutation simply means a reader sees the pre-mutation index, eventually
777
+ * consistent and safe. Crashes inside `work()` release the lock so a single failure
778
+ * does not deadlock subsequent operations.
779
+ */
780
+ private mutationLock;
781
+ constructor(store: BlobStore);
782
+ /** The index, loaded once on first need and cached (mutations replace the cached copy). */
783
+ private loaded;
784
+ private serializeMutation;
785
+ list(dir: string): Promise<readonly DirEntry[]>;
786
+ readText(path: string): Promise<string>;
787
+ readBytes(path: string): Promise<Uint8Array>;
788
+ exists(path: string): Promise<boolean>;
789
+ /**
790
+ * Create or overwrite `key`. The index is rewritten only when `key` is new (an
791
+ * overwrite leaves the key set unchanged, so editing an item is a single `put`).
792
+ *
793
+ * **Auto-stamp** (PROPOSAL §4.1): a destructive write to a template or component
794
+ * path (one that removes a token from the existing source) snapshots the prior
795
+ * bytes to `<base>@v<N+1>.html` before the new bytes land. Order is
796
+ * **current first, snapshot second** (§16.3): if the snapshot copy fails after
797
+ * the current write succeeded, the site stays consistent — only the migration
798
+ * UX's left-pane comparison is unavailable for items affected by this stamp,
799
+ * surfaced as `templates.stamp-incomplete`.
800
+ *
801
+ * Direct writes to a reserved-version path are refused (snapshots are
802
+ * immutable; the user retires them via `delete`, not by overwriting them).
803
+ */
804
+ write(key: string, bytes: Uint8Array): Promise<WriteResult>;
805
+ /**
806
+ * Manually stamp a snapshot of the current `<kind>/<name>.html` to the next available
807
+ * `<name>@v<N+1>.html` slot. Uses the same internal `this.store.put` pathway the
808
+ * auto-stamp uses (so the public `write`'s reserved-version refusal doesn't apply),
809
+ * and runs under the mutation mutex so a concurrent destructive auto-stamp can't
810
+ * race with a manual stamp.
811
+ */
812
+ stamp(name: string, kind: TemplateKind): Promise<StampRecord>;
813
+ /**
814
+ * Delete a file, or a whole directory subtree (every key under `key/`). Idempotent: a
815
+ * path the index does not know is still deleted from the store (clearing an orphan),
816
+ * and deleting nothing is a no-op.
817
+ */
818
+ delete(key: string): Promise<void>;
819
+ /**
820
+ * Move/rename a file, or a whole directory subtree (every key under `from/` is remapped
821
+ * under `to/`). Clobbering an existing destination, or renaming a missing path, are
822
+ * returned as data (`ok: false`), not thrown (CLAUDE §2), the same contract the host's
823
+ * `/api/rename` enforces. (Mutating the reserved namespace is a programmer error and
824
+ * still throws.)
825
+ */
826
+ rename(from: string, to: string): Promise<RenameResult>;
827
+ /**
828
+ * Rebuild this store's index from the *actual* keys the underlying store holds (DESIGN
829
+ * §11d), recovering files that arrived by a path that bypassed the index. A
830
+ * {@link BlobStore} cannot enumerate itself, so the caller supplies the real key set
831
+ * from an adapter that can (e.g. `BlobContainer.list`). Unlike calling
832
+ * {@link reconcileIndex} on a fresh store, this also refreshes the cached in-memory
833
+ * index, so this live instance sees the recovered files immediately.
834
+ */
835
+ reconcile(actualKeys: readonly string[]): Promise<ReconcileResult>;
836
+ }
837
+
613
838
  /**
614
839
  * Redirect generation (DESIGN §9). A move or slug rename changes a page's URL;
615
840
  * internal `ref:` links auto-update, but external/bookmarked/indexed URLs would
@@ -697,27 +922,6 @@ declare const DOCUMENT_SHELL = "document";
697
922
  */
698
923
  declare function loadDocumentShell(source: ContentSource, templatesDir?: string): Promise<string | undefined>;
699
924
 
700
- /**
701
- * The field-type registry (DESIGN §6.7). Field types and their rules are defined
702
- * *once* here and shared by the compiler, the editor's form generator, and (later)
703
- * Monaco's IntelliSense. This is the OCP extension point (CLAUDE.md §3): adding a
704
- * field type means adding an entry here, never editing a switch in the compiler or
705
- * the inference cascade.
706
- */
707
- type FieldType = 'image' | 'file' | 'url' | 'email' | 'phone' | 'date' | 'time' | 'code' | 'richtext' | 'authors' | 'text' | 'shorttext';
708
- /** How a resolved value is placed into output, the compiler reads this, never the type name. */
709
- type ValueKind = 'text' | 'html' | 'url' | 'asset' | 'authors';
710
- interface FieldTypeDef {
711
- readonly type: FieldType;
712
- readonly valueKind: ValueKind;
713
- /** Default editor control hint, consumed by the form generator (DESIGN §7). */
714
- readonly control: string;
715
- readonly multiline: boolean;
716
- }
717
- declare const FIELD_TYPES: Readonly<Record<FieldType, FieldTypeDef>>;
718
- declare function isFieldType(value: string): value is FieldType;
719
- declare function valueKindOf(type: FieldType): ValueKind;
720
-
721
925
  /**
722
926
  * Contextual token inference (DESIGN §6.2). A token's control type is inferred from
723
927
  * *where it sits*, via a precedence cascade:
@@ -768,6 +972,95 @@ declare function findTokens(input: string): TokenRef[];
768
972
  /** If the trimmed input is exactly one token, return it; otherwise null. */
769
973
  declare function wholeValueToken(input: string): TokenRef | null;
770
974
 
975
+ /**
976
+ * Versioned-name conventions for templates + components (PROPOSAL §3, §2.9). A snapshot
977
+ * lives at the same path as its current sibling with an `@v<N>` suffix appended to the
978
+ * base name, e.g. `templates/article.html` (current) and `templates/article@v1.html`
979
+ * (snapshot). The suffix is reserved: the engine refuses to mutate paths into or out of
980
+ * the form, so users can't accidentally collide with it.
981
+ *
982
+ * Canonical form is strict: `@v` followed by a positive base-10 integer with no leading
983
+ * zeros, exactly one suffix per name. `@v01`, `@v`, `@v1@v2` are not versions, just
984
+ * unusually-named bare templates — the helper returns false rather than try to repair.
985
+ */
986
+ /** True when `name` parses as `<base>@v<N>` in canonical form (no nesting). */
987
+ declare function isVersionedTemplateName(name: string): boolean;
988
+ /** The base name without any `@v<N>` suffix (returns the input unchanged if unversioned). */
989
+ declare function baseTemplateName(name: string): string;
990
+ /** The numeric version, or `null` if `name` is not in canonical versioned form. */
991
+ declare function versionNumber(name: string): number | null;
992
+ /** Build the canonical snapshot name for `base` at `version`. Throws on invalid input. */
993
+ declare function snapshotName(base: string, version: number): string;
994
+ /**
995
+ * The next version slot to allocate, given the names of every snapshot already in play
996
+ * (typically the result of enumerating siblings of the current template). One higher than
997
+ * the maximum existing version; 1 if no snapshots exist. Gaps are preserved (deleting a
998
+ * snapshot does not reuse its number) — the user can see gaps in their tree but the
999
+ * sequence remains monotonic, matching the proposal §16.5 decision.
1000
+ */
1001
+ declare function nextVersionNumber(existingNames: readonly string[]): number;
1002
+ /**
1003
+ * True when `path` matches the canonical snapshot form for a template or component (under
1004
+ * `templates/` or `components/`, ending in `.html`, base name has an `@v<N>` suffix).
1005
+ * Used by {@link IndexedStore} to refuse renames into or out of the reserved namespace.
1006
+ *
1007
+ * Matching paths in other partitions (content, public) are *not* reserved — users can
1008
+ * name content files however they like; the engine only owns the convention inside the
1009
+ * partitions whose tokens it interprets.
1010
+ */
1011
+ declare function isReservedVersionedPath(path: string): boolean;
1012
+
1013
+ /**
1014
+ * Template-version migration helpers (PROPOSAL-template-versioning §4.3, §6).
1015
+ *
1016
+ * `pendingMigrations` enumerates content items whose JSON has fields that don't match
1017
+ * the schema of their bound template — orphan fields (data the template no longer
1018
+ * renders) or missing required fields (template wants but JSON is empty). Drift is
1019
+ * computed per-item against the item's *bound* template (current name or snapshot pin),
1020
+ * so pinned items are still flagged if the pin itself has drift.
1021
+ *
1022
+ * `bestFitSnapshot` picks the most recent snapshot of a base whose tokens are a
1023
+ * superset of an item's fields — used by the migration UX's left-pane render to show
1024
+ * "this is how the item rendered before."
1025
+ *
1026
+ * `applyMigration` rewrites an item JSON per a user-supplied resolution (drop / rename
1027
+ * / keep / fill). Idempotent in the sense that a no-op resolution leaves the JSON
1028
+ * byte-identical; non-resolved keys are preserved.
1029
+ */
1030
+ interface PendingMigrationItem {
1031
+ /** Full content path (e.g. "content/blog/post.json"). */
1032
+ readonly path: string;
1033
+ /** The item's `template` field — e.g. "article" or "article@v1". */
1034
+ readonly boundTemplate: string;
1035
+ /** The base name (no `@v<N>` suffix). For pinned items this is the family. */
1036
+ readonly currentTemplate: string;
1037
+ /** Fields in JSON that the bound template doesn't render. */
1038
+ readonly orphanFields: readonly string[];
1039
+ /** Required fields the bound template wants but the JSON's `fields` is empty for. */
1040
+ readonly missingRequiredFields: readonly string[];
1041
+ /** Best-fit snapshot name (e.g. "article@v2") for the migration UX's left pane,
1042
+ * or `null` when no snapshot's tokens cover the item's fields. */
1043
+ readonly bestFitSnapshot: string | null;
1044
+ }
1045
+ interface PendingMigrations {
1046
+ readonly items: readonly PendingMigrationItem[];
1047
+ /** Items grouped by `currentTemplate` for the workspace's list view. */
1048
+ readonly byTemplate: ReadonlyMap<string, readonly PendingMigrationItem[]>;
1049
+ }
1050
+ interface MigrationResolution {
1051
+ /** Orphan field names to remove from the item JSON. */
1052
+ readonly drop: readonly string[];
1053
+ /** Map of orphan field → current-template field to copy the value into. */
1054
+ readonly rename: Readonly<Record<string, string>>;
1055
+ /** Orphan field names to leave in the item JSON (advisory; gate stops warning). */
1056
+ readonly keep: readonly string[];
1057
+ /** Map of current-template field → value to fill (for missing required fields). */
1058
+ readonly fill: Readonly<Record<string, string>>;
1059
+ }
1060
+ declare function pendingMigrations(store: WorkingStore): Promise<PendingMigrations>;
1061
+ declare function bestFitSnapshot(store: WorkingStore, base: string, itemFieldNames: readonly string[]): Promise<string | null>;
1062
+ declare function applyMigration(store: WorkingStore, itemPath: string, resolution: MigrationResolution): Promise<void>;
1063
+
771
1064
  /**
772
1065
  * The authoring reference (DESIGN §14). A single, generated description of the whole
773
1066
  * template surface, every field type, annotation, loop, and token, that powers three
@@ -853,42 +1146,6 @@ declare function buildRss(entries: readonly PageEntry[], options: RssOptions): A
853
1146
  */
854
1147
  declare function buildContentIndex(entries: readonly PageEntry[]): Artifact;
855
1148
 
856
- /**
857
- * Derive the editor's form from a template, "the template is the schema"
858
- * (DESIGN §5.5/§6). Walking the same parse the compiler uses, each page-scope
859
- * token becomes one field whose control is inferred from where it sits, deduped by
860
- * name and labelled. This is the single source of truth the editor's form
861
- * generator and the compiler share (DESIGN §6.7).
862
- *
863
- * Inference is **component-aware**: when a component is used (`<doc file="{x}">`),
864
- * the bound field's type comes from how that prop is used *inside* the component,
865
- * not from the attribute's position on the usage. A component's prop types are
866
- * simply the field types of its own body, so the same derivation resolves them,
867
- * recursively, through nested components, with a cycle guard.
868
- */
869
- interface DerivedField {
870
- readonly name: string;
871
- readonly type: FieldType;
872
- readonly label: string;
873
- readonly required: boolean;
874
- readonly multiline: boolean;
875
- readonly help?: string;
876
- /** Minimum character length (`data-minlength`); the gate warns when shorter. */
877
- readonly minLength?: number;
878
- /** Maximum character length (`data-maxlength`); the gate warns when longer. */
879
- readonly maxLength?: number;
880
- /** A curated multi-reference (a `data-each` loop field). */
881
- readonly multiple?: boolean;
882
- /** Collection the reference picker is scoped to (`data-pick-from`). */
883
- readonly pickFrom?: string;
884
- }
885
- /** Author-declared length bounds on a field value (`data-minlength`/`data-maxlength`). */
886
- interface LengthConstraints {
887
- readonly minLength?: number;
888
- readonly maxLength?: number;
889
- }
890
- declare function deriveFields(template: string, components?: ComponentMap): DerivedField[];
891
-
892
1149
  /**
893
1150
  * Static analysis of a template's structure, used by the validation gate, the
894
1151
  * media phase, and (later) the editor. Extracts the signals downstream needs:
@@ -1318,7 +1575,15 @@ type Severity = 'error' | 'warning' | 'info';
1318
1575
  * coarse and stable — adding adapter-specific categories ("kv", "cloudflare", …) would
1319
1576
  * couple the engine to specific cloud concepts, which is what we are avoiding.
1320
1577
  */
1321
- type Source = 'content' | 'index' | 'auth' | 'connectivity';
1578
+ type Source = 'content' | 'index' | 'auth' | 'connectivity' | 'templates';
1579
+ /**
1580
+ * Arguments a repair handle carries through to its `Repair.run`. Plain string map so the
1581
+ * shape serialises cleanly across the API boundary; repairs that need richer types parse
1582
+ * them inside `run`. Per-item context (an item path, a snapshot name) lives here when one
1583
+ * generic repair handles many findings (e.g. `templates.rebind-item-to-current` rebinds
1584
+ * whichever path it's given).
1585
+ */
1586
+ type RepairArgs = Readonly<Record<string, string>>;
1322
1587
  /**
1323
1588
  * One thing the diagnostics gate found wrong (or noteworthy). Shape mirrors the
1324
1589
  * validation gate's {@link Diagnostic} type so a future merger is one step.
@@ -1336,6 +1601,8 @@ interface Finding {
1336
1601
  readonly repair?: {
1337
1602
  readonly id: string;
1338
1603
  readonly label: string;
1604
+ /** Per-finding context (e.g. an item path) the registered repair needs to run. */
1605
+ readonly args?: RepairArgs;
1339
1606
  };
1340
1607
  }
1341
1608
  /**
@@ -1359,11 +1626,12 @@ interface Diagnostic {
1359
1626
  /**
1360
1627
  * One in-place fix. Idempotent: calling `run` twice does not double-write. The host
1361
1628
  * re-runs the diagnostic set after a repair to refresh the UI, so repairs don't have to
1362
- * return findings themselves.
1629
+ * return findings themselves. `args` carries per-finding context from the {@link Finding}
1630
+ * that surfaced the repair handle (e.g. the item path a "rebind to current" repair acts on).
1363
1631
  */
1364
1632
  interface Repair {
1365
1633
  readonly id: string;
1366
- run(deps: DiagnoseDeps): Promise<void>;
1634
+ run(deps: DiagnoseDeps, args: RepairArgs): Promise<void>;
1367
1635
  }
1368
1636
 
1369
1637
  /**
@@ -1384,11 +1652,12 @@ interface DiagnosticRegistry {
1384
1652
  addRepair(repair: Repair): void;
1385
1653
  /** Run every registered diagnostic in order; concatenate their findings. */
1386
1654
  runAll(deps: DiagnoseDeps): Promise<readonly Finding[]>;
1387
- /** Run the named repair, then return a fresh `runAll` so the UI re-renders. */
1388
- runRepair(id: string, deps: DiagnoseDeps): Promise<readonly Finding[]>;
1655
+ /** Run the named repair with optional per-finding args, then return a fresh `runAll`
1656
+ * so the UI re-renders. Args default to `{}` when the repair needs none. */
1657
+ runRepair(id: string, deps: DiagnoseDeps, args?: RepairArgs): Promise<readonly Finding[]>;
1389
1658
  }
1390
1659
  declare function createDiagnosticRegistry(): DiagnosticRegistry;
1391
1660
 
1392
1661
  declare const workingStoreRoundTripDiagnostic: Diagnostic;
1393
1662
 
1394
- export { type Artifact, type ArtifactSink, type AuthEndpoints, type AuthResult, type AuthorDirectory, type AuthorEntry, type AuthorOption, type AuthorRef, type AuthoringReference, type BlobStore, type BoundItem, type ChangePasswordRequest, type ChangePasswordSuccess, type CollectionConfig, type CollectionQuery, type CompileInput, type CompilePageOptions, type CompileSiteOptions, type CompiledPage, type ComponentMap, type ContentIndex, type ContentItem, ContentParseError, type ContentSource, type CreateTokenSuccess, type CreateUserRequest, DEFAULT_DIRS, DOCUMENT_SHELL, type DerivedField, type DiagnoseDeps, type Severity as DiagnoseSeverity, type Source as DiagnoseSource, type Diagnostic$1 as Diagnostic, type Diagnostic as DiagnosticCheck, type DiagnosticRegistry, type DirEntry, type DirNode, type EncodeRequest, type EncodedImage, type EncodedVariant, type EntryKind, FIELD_TYPES, type FieldPrimitive, type FieldRecord, type FieldType, type FieldTypeDef, type FieldValue, type Finding, type IdentityProvider, type ImageEncoder, type ImageFormat, type ImageInfo, InMemoryArtifactSink, InMemoryBlobStore, InMemoryContentSource, IndexedStore, type ItemNode, type LengthConstraints, type LoginRequest, type LoginSuccess, type MediaResolver, type PageEntry, type PreBuildHook, type Principal, type PublishOptions, type PublishResult, type PublishSummary, type PurgeService, RESERVED_PREFIX, type ReconcileResult, type RedirectRule, type ReferenceContext, type ReferenceEntry, type ReferenceSection, type RefreshSuccess, type RenameResult, type Repair, type ResetPasswordRequest, type ResolveContext, type Role, type RssOptions, type Scope, type Severity$1 as Severity, type SiteConfig, type SortFile, type TemplateAnalysis, type TokenContext, type TokenRef, type TreeNode, type UpdateUserRequest, type UserAdminEndpoints, type UserSummary, type ValidationResult, type ValueKind, type WorkingStore, analyzeTemplate, buildAuthoringReference, buildContentIndex, buildPictureMarkup, buildRedirects, buildResolveContext, buildRss, buildSitemap, canEdit, compilePage, compileSite, compileTemplate, contentHash, contentTypeFor, createDiagnosticRegistry, deriveFields, emptyIndex, escapeHtmlAttribute, escapeHtmlText, escapeJsonStringContent, findTokens, hasRole, humanize, inferControl, isFieldType, joinAuthors, loadComponentScripts, loadComponentStyles, loadComponents, loadContentTree, loadDocumentShell, loadIndex, loadRedirects, loadSiteConfig, loadTemplate, noopPurgeService, outputPathForItem, parseContentItem, parseRedirects, parseSortFile, processImage, publishSite, reconcileIndex, renderAuthors, renderReferenceMarkdown, sanitizeUrl, saveIndex, slugify, textContent, toAuthorRefs, urlForItem, validateSite, valueKindOf, wholeValueToken, workingStoreRoundTripDiagnostic };
1663
+ export { type Artifact, type ArtifactSink, type AuthEndpoints, type AuthResult, type AuthorDirectory, type AuthorEntry, type AuthorOption, type AuthorRef, type AuthoringReference, type BlobStore, type BoundItem, type ChangePasswordRequest, type ChangePasswordSuccess, type CollectionConfig, type CollectionQuery, type CompileInput, type CompilePageOptions, type CompileSiteOptions, type CompiledPage, type ComponentMap, type ContentIndex, type ContentItem, ContentParseError, type ContentSource, type CreateTokenSuccess, type CreateUserRequest, DEFAULT_DIRS, DOCUMENT_SHELL, type DerivedField, type DiagnoseDeps, type Severity as DiagnoseSeverity, type Source as DiagnoseSource, type Diagnostic$1 as Diagnostic, type Diagnostic as DiagnosticCheck, type DiagnosticRegistry, type DirEntry, type DirNode, type EncodeRequest, type EncodedImage, type EncodedVariant, type EntryKind, FIELD_TYPES, type FieldPrimitive, type FieldRecord, type FieldType, type FieldTypeDef, type FieldValue, type Finding, type IdentityProvider, type ImageEncoder, type ImageFormat, type ImageInfo, InMemoryArtifactSink, InMemoryBlobStore, InMemoryContentSource, IndexedStore, type ItemNode, type LengthConstraints, type LoginRequest, type LoginSuccess, type MediaResolver, type MigrationResolution, type PageEntry, type PendingMigrationItem, type PendingMigrations, type PreBuildHook, type Principal, type PublishOptions, type PublishResult, type PublishSummary, type PurgeService, RESERVED_PREFIX, type ReconcileResult, type RedirectRule, type ReferenceContext, type ReferenceEntry, type ReferenceSection, type RefreshSuccess, type RenameResult, type Repair, type RepairArgs, type ResetPasswordRequest, type ResolveContext, type Role, type RssOptions, type SchemaDelta, type SchemaFieldRef, type Scope, type Severity$1 as Severity, type SiteConfig, type SortFile, type StampDecision, type StampRecord, type TemplateAnalysis, type TemplateKind, type TokenContext, type TokenRef, type TreeNode, type TypeChange, type UpdateUserRequest, type UserAdminEndpoints, type UserSummary, type ValidationResult, type ValueKind, type WorkingStore, analyzeTemplate, applyMigration, baseTemplateName, bestFitSnapshot, buildAuthoringReference, buildContentIndex, buildPictureMarkup, buildRedirects, buildResolveContext, buildRss, buildSitemap, canEdit, compilePage, compileSite, compileTemplate, computeSchemaDelta, contentHash, contentTypeFor, createDiagnosticRegistry, deriveFields, detectStamp, emptyIndex, escapeHtmlAttribute, escapeHtmlText, escapeJsonStringContent, findTokens, hasRole, humanize, inferControl, isDestructiveTypeChange, isFieldType, isReservedVersionedPath, isVersionedTemplateName, joinAuthors, loadComponentScripts, loadComponentStyles, loadComponents, loadContentTree, loadDocumentShell, loadIndex, loadRedirects, loadSiteConfig, loadTemplate, nextVersionNumber, noopPurgeService, outputPathForItem, parseContentItem, parseRedirects, parseSortFile, pendingMigrations, processImage, publishSite, reconcileIndex, renderAuthors, renderReferenceMarkdown, sanitizeUrl, saveIndex, slugify, snapshotName, textContent, toAuthorRefs, urlForItem, validateSite, valueKindOf, versionNumber, wholeValueToken, workingStoreRoundTripDiagnostic };