Implementation Plan: ANU-18 - Add Bento Host-Save, Stable Focus, and Packaged Template Catalog
Scope
- Extend the closed
anuva/bento-editorhost request protocol with: request-savecarrying exactly{ trigger: "manual" | "autosave" }; andfocuscarrying exactly{ surface, slideId, sceneId? }.- Route host-requested saves through the same validated session-save path as the
visible editor Save control and
Ctrl+S, preserving the hostrequestId, the current accepted base revision, the requested trigger, and the complete dehydrated presentation envelope. - Reject invalid or duplicate host request IDs deterministically, preserve correlation where a valid request ID is available, and leave accepted revision, content, dirty state, and history unchanged on failure.
- Track the real active slide independently for Main, Companion, and Emphasis. Validate surface and slide ownership, preserve each surface's active slide across switches, and focus through the supported Bento Store navigation operation without mutating document or history state.
- Generate one byte-deterministic Signal/Paper template-family catalog from the
same
createAnuvaTemplateFamilies()runtime source used by the editor. - Package the generated JSON and expose its relative path, catalog format version, SHA-256, and ordered family IDs in the editor artifact manifest.
- Advance:
- editor protocol version to
1.1.0; - editor artifact version to
1.1.0; and @anuva/bento-contractpackage version to1.1.0.- Advertise exact editor capabilities:
editor.host-request-save;editor.focus.stable; andtemplates.catalog.packaged.- Preserve presentation contract
1.0.0, player protocol and artifact1.0.0, renderer1.0.8-anuva-renderer.1, template-family object schema1.0.0, hard-offline behavior, origin and parent-source enforcement, license, and third-party notices.
Product Main inputs and dependencies
- Linear issue: ANU-18.
- Parent issue: ANU-17,
Anuva Bento Fix for ANU-14 readiness gate. - Product Main source:
docs/changes/2026-07-27-anu-17-bento-readiness-gate/index.md. - Product Main review preview: https://main1.girishd.com/changes/2026-07-27-anu-17-bento-readiness-gate/.
- Repository label:
anuva-bento. - Blockers: none.
- Planning base: downstream
mainatbef9c3f49fe1d7018b495f3987ba4657d358ff10. - ANU-12 supplies the production editor baseline:
- closed editor request validation and JSON Schema;
- host-owned accepted revisions and validated
save-requestevents; - one composite session over three independent surface documents;
- Signal and Paper runtime template-family objects;
- composite undo/redo;
- exact-origin and parent-source bridge validation;
- hard-offline editor packaging with license and notices; and
- a real repository browser host/editor harness.
- This repository owns protocol types, runtime validation, JSON Schema, bridge dispatch, editor session and Store adapter boundaries, template catalog generation, manifests, packages, tests, and normative Bento documentation.
- CMS persistence, autosave policy, scene-to-slide mapping, AI orchestration, product Web preview UX, Python staging, Unity/Vuplex hosting, and downstream ANU-14 acceptance remain outside this repository.
Implementation approach
1. Freeze version and compatibility authority
- Record the branch base, upstream base, Node, npm, TypeScript, Vite, Bento, renderer, presentation contract, player, editor, protocol, family-schema, and package versions before changing behavior.
- Keep distinct authorities explicit:
- presentation DTO
contractVersionremains1.0.0; - player protocol and player artifact remain
1.0.0; - template-family objects keep
schemaVersion: "1.0.0"and their current family versions; - only the contract package distribution, editor protocol, and editor
artifact advance to
1.1.0. - Add or expose a package-version constant if necessary so package distribution versioning is not confused with the preserved presentation DTO version.
- Extend the editor capability list with the three exact capability identifiers in Scope while retaining all existing editor capabilities.
- Make ready/diagnostic data and the artifact manifest advertise the applicable versions and capabilities from shared constants rather than copied literals.
2. Define exact closed protocol shapes
- Replace the broad optional editor-request payload model with a discriminated, command-specific TypeScript union so each command has one exact payload.
- Add:
request-savewith required payload{ trigger: "manual" | "autosave" }; andfocuswith required payload{ surface, slideId, sceneId? }.- Keep
sceneIdas validated, correlated host context only. Bento does not derive scene mapping or persist it into the presentation. - Update runtime validation and
schemas/editor.schema.jsontogether: - every command shape is closed with
additionalProperties: false; - required fields are command-specific;
- unknown commands, fields, triggers, surfaces, and malformed IDs produce stable issue codes and JSON-style paths; and
- protocol
1.0.0and future versions fail before bridge dispatch. - Cover request, response, event, save-trigger, and focus payloads in the distributed schema so TypeScript, runtime validation, and JSON Schema describe identical public shapes.
- Retain exact origin and parent-window source checks before validation or dispatch.
3. Make request identity and host-save behavior deterministic
- Track accepted host request IDs for the lifetime of the loaded editor session.
A repeated ID returns a correlated
DUPLICATE_REQUEST_IDfailure and never dispatches the command again. - Do not reserve an ID that cannot itself be validated. When a structurally
recognizable stable
requestIdaccompanies an otherwise invalid request, return the stable validation failure against that same ID. - Define load as a new session boundary for duplicate tracking only if the successfully validated load request completes; document and test that rule.
- Refactor bridge Save control,
Ctrl+S, andrequest-saveto call oneAnuvaEditorSession.saveRequest(requestId, trigger)path. - For interactive Save and
Ctrl+S, create an editor-owned stable request ID and use triggermanual. - For a host request:
- preserve its exact
requestId; - preserve the requested
manualorautosavetrigger; - use the current accepted revision as
baseRevision; - capture and dehydrate the active surface;
- validate the complete presentation; and
- emit the existing
save-requestevent with the full envelope. - Return a normal correlated response indicating that the save request was
emitted. Persistence still succeeds only after a separate valid
save-accepted. - On validation failure, emit or return the stable correlated
SAVE_VALIDATION_FAILEDshape, do not emitsave-request, and do not advance accepted revision or clear dirty state.
4. Preserve the real active slide per surface
- Extend the narrow production Bento scripting/session adapter with read-only
current-slide identity plus navigation by stable slide ID implemented through
Store.goTo(index). - Do not expose direct
currentIndexmutation or a second navigation/history implementation. - Initialize a per-surface active-slide map from each surface's first slide.
- Listen for supported Store
currentevents and update only the active surface's remembered slide. - Before switching surfaces, capture the active document and its current slide. After loading the destination surface document, restore its remembered slide through the Store operation.
- After host load, operation application, undo, or redo:
- preserve a remembered slide that still exists;
- otherwise choose the first slide deterministically; and
- never retain a slide ID owned by another surface.
- Implement
focusas: - validate the requested surface;
- prove the target slide exists on that surface;
- switch/materialize the target surface if needed;
- navigate through the Store adapter; and
- report the resulting
{ surface, slideId, sceneId? }. - Return stable structured errors for missing targets and cross-surface targets. Repeated focus to the already active target is successful and idempotent.
- Snapshot the complete envelope, accepted revision, dirty flag, session undo/redo availability, and Bento document/history state around focus tests to prove navigation changes none of them.
5. Generate one deterministic runtime-equal template catalog
- Add a server-safe catalog contract:
- format
anuva/bento-template-catalog; - format version
1.0.0; - closed top-level fields; and
- an ordered
familiesarray containing normal template-family objects. - Add TypeScript types, shared constants, runtime validation, and JSON Schema coverage without changing the template-family object schema version.
- Add a build script that imports
createAnuvaTemplateFamilies()directly, validates every family and the complete catalog, and writes normalized UTF-8 JSON with one trailing newline. - Do not maintain a copied JSON fixture or second Signal/Paper source. Tests must deep-compare parsed catalog families to freshly created runtime families.
- Preserve runtime family order and expose the corresponding ordered family IDs.
- Generate into the editor build output before artifact file enumeration so the packaged bytes and their digest are stable and covered by clean rebuilds.
6. Package and verify editor 1.1.0
- Update editor HTML/runtime metadata, package paths, and test harness labels
from ANU-12/
1.0.0to ANU-18/1.1.0where they describe the changed editor. - Package under
working/anu-18/anuva-bento-editor-1.1.0/. - Add the catalog JSON to the distributed files and extend
manifest.jsonwith a closed catalog descriptor containing: - relative catalog path;
- format version;
- lowercase SHA-256; and
- ordered family IDs.
- Verify the descriptor digest equals both the catalog bytes and its normal entry in the manifest file list.
- Retain exact renderer, Bento, presentation-contract, protocol, editor, template-family, hard-offline, and persistence-authority metadata.
- Retain
LICENSE,THIRD_PARTY_NOTICES.md, presentation schema, editor schema, and all existing prohibited-marker and public-network checks. - Build and dry-run pack
@anuva/bento-contract1.1.0, confirming that its editor schema, compatibility metadata, declarations, license, and notices are included and that a Node import remains DOM/browser-free.
7. Exercise the real host/editor flow
- Extend focused contract tests for every valid and invalid command variant, closed-field parity, version rejection, trigger validation, focus identity, catalog validation, package version, and capabilities.
- Extend session/bridge tests for:
- manual and autosave host requests;
- visible Save and
Ctrl+Sconvergence on the same session path; - preserved host request ID, base revision, trigger, and full envelope;
- invalid content and duplicate request IDs;
- no accepted-revision advance on failure;
- non-first-slide focus on Main, Companion, and Emphasis;
- cross-surface switching and remembered active slide;
- missing and cross-surface target errors;
- repeated-focus idempotency; and
- unchanged content, dirty state, revision, undo, and redo.
- Extend the real browser host/editor harness to load the packaged catalog, verify its manifest digest and family IDs, perform manual and autosave correlation, focus every surface and non-first slides, and assert structured failures.
- Deny every public-network request while allowing only artifact-local catalog loading and the configured host/editor origin.
- Capture browser console errors, unhandled rejections, manifest/catalog mismatches, and unexpected requests as hard failures.
8. Document, verify, and hand off
- After explicit plan approval, create
ImplementationLog.mdand record decisions, source changes, commands, versions, network behavior, generated bytes, hashes, browser evidence, and skipped checks. - Update durable documentation for:
- editor-host protocol
1.1.0, exact command/event shapes, triggers, correlation, duplicate IDs, and revision authority; - stable focus, per-surface active-slide reporting, ownership failures, and navigation idempotency;
- template catalog format, generation authority, equality, and versioning;
- contract-package versus presentation-contract versions;
- editor capabilities and compatibility;
- structured errors;
- hard-offline and origin/source security;
- package/manifest fields, paths, digests, license, and notices; and
- browser and deterministic-build verification.
- Maintain recursive indexes and MkDocs navigation after each logical docs update and return exact machine preview URLs.
- Produce
CompletionReport.mdmapping every Linear acceptance item to exact evidence and recording reviewed commit, draft PR, artifacts, versions, capabilities, manifest and catalog hashes, limitations, recovery state, preview URLs, and the Product Main/ANU-14 handoff. - Run
anuva pr create ANU-18 --draft --confirm. Do not merge or mark Done.
Documentation impact
- This planning step adds only:
- this change index;
- this ImplementationPlan; and
- the recursive index and MkDocs navigation entries required to preview them.
- After explicit approval, update:
docs/editor/EditorHostProtocol.md;docs/editor/TemplateFamilies.md;docs/editor/SecurityAndPackaging.md;docs/contracts/Compatibility.md;docs/contracts/Errors.md;docs/contracts/PackagingAndRelease.md;docs/contracts/AssetsAndSecurity.mdwhere hard-offline catalog loading requires clarification;docs/repository/Architecture.mdanddocs/repository/SecurityAndLicensing.mdonly for durable boundary changes;- editor, contracts, changes, and repository indexes as needed; and
- this change's
ImplementationLog.mdandCompletionReport.md. - Preview documentation remains non-canonical until separately approved.
Verification and acceptance checks
- Baseline and regression, from
slides/unless stated otherwise: - record exact tool and dependency versions;
npm ci;npm run build;- the documented Windows-equivalent upstream single-file build;
node ..\scripts\test-sync.ts;npm run test:anuva;npm run test:editor;npm run build:anuva; and- existing player build/package regression where shared constants or compatibility metadata could affect it.
- Contract and schema:
npm run build:contract;- TypeScript declaration and Node import checks;
- TypeScript/runtime/JSON-Schema parity for every closed request and catalog shape;
- valid, malformed, unknown-field, unknown-trigger, old-version, future-version, duplicate-ID, missing-target, and cross-surface fixtures;
- stable error code and JSON-path snapshots;
- presentation contract/player/template-family version preservation; and
- package/editor/protocol
1.1.0plus exact capability assertions. - Save correlation:
- host manual and autosave requests;
- visible Save and
Ctrl+S; - exact request ID, trigger, base revision, and complete envelope;
- invalid presentation and repeated request IDs; and
- unchanged accepted revision and recovery state after rejection.
- Focus:
- Main, Companion, and Emphasis;
- first and non-first slides;
- repeated same-surface and cross-surface transitions;
- remembered per-surface active slides;
- missing and wrong-surface targets;
- optional
sceneIdcorrelation without scene interpretation; and - byte-equal content plus unchanged dirty/revision/undo/redo state.
- Catalog and packaging:
npm run package:editor;- contract
npm run buildandnpm pack --dry-run; - two clean catalog/editor artifact rebuilds;
- byte and SHA-256 comparison across rebuilds;
- parsed catalog deep equality with runtime Signal/Paper objects;
- manifest path, format version, SHA-256, family ID, file-entry, version, capability, hard-offline, renderer, license, and notice inspection; and
- proof that no generated catalog is maintained independently from runtime family source.
- Browser and security:
- direct production host/editor artifact smoke;
- manual/autosave correlation and duplicate failure;
- every surface, non-first-slide focus, and cross-surface restoration;
- packaged catalog fetch, digest, validation, and equality;
- structured invalid-save, duplicate-ID, missing-slide, and wrong-surface failures;
- exact origin and parent-source denial;
- no public request, redirect, update, collaboration, or alternate persistence traffic; and
- no page error, unhandled rejection, or unexpected console failure.
- Documentation:
anuva docs validate-indexes --repository current;- strict MkDocs build through the guarded preview workflow;
- fresh live-page comparison since the recorded pre-edit timestamp; and
- exact valid HTTPS preview links for every changed page.
Non-goals and rollback
- No CMS persistence implementation, database write, accepted-revision assignment, autosave scheduling or policy, conflict-resolution policy, or PresentationConfig compilation.
- No scene mapping or inference;
sceneIdis correlation context only. - No AI provider/model call, prompt workflow, Web-host product preview, asset upload, Python orchestration, Unity/Vuplex lifecycle, virtual-screen mapping, capture, or downstream ANU-14 implementation.
- No iframe workaround, broad upstream Store/editor rewrite, presentation DTO version change, player protocol/artifact change, renderer change, template-family object-schema change, or unrelated upstream synchronization.
- No registry publication, GitHub release, production deployment, canonical docs publication, PR merge, or Linear completion.
- Before merge, rollback is removal of the ANU-18 protocol
1.1.0additions, active-slide adapter/session behavior, catalog generator and manifest fields, focused tests, generated local artifacts, and ANU-18 documentation from the feature branch. ANU-12 editor1.0.0, presentation/player1.0.0, and the runtime Signal/Paper sources remain the recovery baseline.
Approval
Girish separately approved this ImplementationPlan on 2026-07-27 before implementation began.