Fusion - the Fusion 360 Bridge
Public Made by Adomby adom
Drive Autodesk Fusion 360 from the cloud via Adom Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.
master
b2d7cdb
26d ago
Native document lifecycle port
Status: design audit, 2026-10-14. Product source is unchanged by this document. The next useful slice is native blank-design creation with exact identity adoption, explicit owned-scratch discard, and exact-ID activation. Optional box construction, transaction probing, general document close/save, and full legacy inspection remain separate qualification obligations. A small isolated Rust test-fixture add-in can qualify SDK lifecycle behavior before exposing these product operations.
Source and contract audit
Legacy paths below are relative to ../exploded-preview-preparation/runtime-dev9-build-r1/source/addin/AdomBridge/.
| Source | Actual behavior and port consequence |
|---|---|
commands/mechanical/operations.py:97 |
new_design validates a requested label (default Adom mechanical, 1–120 characters) and optional positive finite width/height/depth in mm. It retains the previous active object, calls documents.add(FusionDesignDocumentType), resolves that document's Design product, and sets parametric design type. |
| Same function | If the session transaction backend is unverified, creation runs the mutation/abort/commit/recovery probe in the new design. Optional box creates three driving user parameters, a dimensioned XY rectangle, and an extrusion. It recomputes/checks health and returns full legacy inspection. Blank creation alone does not implement these semantics. |
| Same function | Requested label is an AdomMechanical/requestedName root attribute, not Document.name. Failure cleanup checks the retained document is unsaved and starts with Untitled, invokes close(False) without checking its Boolean, then tests validity. Previous-document activation ignores its Boolean and identity readback. Preserve the useful naming precaution; replace these weak outcome checks. |
commands/close_document.py:16,82 |
General close selects the first exact name or the active document; it attempts to terminate/abort an active command, executes SelectCommand and pumps events. For a modified cloud document it may save a new version even when save=false, then ignores the close Boolean. Do not carry those hidden effects into owned-scratch cleanup. |
commands/close_document.py:176 |
Bulk close snapshots the original list because Fusion may create a replacement Untitled when the last document closes. It has independent skip/force/save rules. The native scratch operation closes exactly one retained object and never loops on document count. |
commands/document_info.py:176 |
Activation accepts substring name/type/data-file filters, favors exact names, and may try another matching candidate after failure. Its final verification compares active names; a failed active-name getter can leave verification incomplete. Native activation uses one current registry ID and SDK object equality, with one invocation. |
commands/mechanical/exploded_preview.py:94,146 |
Preview adoption requires a coherent current-session succeeded new_design journal receipt with matching request digest/target and unsaved state, plus exact live retained object, active state, blank-model witness, and an exclusive session lease. History never reconstructs native ownership after reload. Preserve this separation of durable creation evidence from a live capability. |
mechanical/schema.json:/new_design |
Promises an unnamed unsaved parametric hybrid design and optional parameter-driven box. New native capabilities must describe their implemented subset and keep legacyParity:false until the missing paths are qualified. |
Installed SDK headers were read under C:/Users/drew/AppData/Roaming/Autodesk/Autodesk Fusion 360/API/CPP/include. The following official references were checked on 2026-10-14:
- Documents.add: creation returns the created document, currently requires visible creation, and is unsupported within Command-related events/transactions. The official creation sample says default creation is hybrid; verify actual
Design.designIntentrather than inventingNamedValuesoption keys. - Document.close: close has the same Command restriction, returns a Boolean, and
saveChanges=truecan prompt.falseis the documented discard choice. Legacy comments and the local no-modal skill record narrower empirical prompt hazards for named unsaved documents; those are local qualification constraints, not an extra official API guarantee. - Document.activate: changes the active document and returns a Boolean. The result requires exact active-object readback.
- UserInterface.activeCommand exposes a command ID. No documented global “transaction open” getter was found in the examined headers. A custom event reaching the main thread is not proof that create/close is allowed.
Core/Application/Document.h:50–76,148–157: names may be changed before first save;creationId, names and saved/modified flags are observations, not unique ownership capabilities. Copies may share creation metadata.Fusion/Fusion/Design.h:72–79,333–348: design type and design intent are distinct. Changing an existing parametric design to direct destroys history. Set type only on the exact newly returned design and read it back.Fusion/Components/Component.h:295–298: component revision changes with component changes. It is not a documented whole-Design revision; the currentparameters-v1projection is explicitly scoped and cannot be relabeled a complete document-content guard.
Apply fusion-no-modal-dialogs: retain the untouched native scratch name, never silently save to make close possible, refuse an unknown command or prompt-prone target before invocation. Do not add dialog sweeping, automatic command termination, event pumping, or screenshot loops.
Small implementation slices
- Isolated lifecycle fixture, not a product capability. A manually loaded Rust test DLL creates one blank unsaved parametric hybrid design, retains exact created/prior SDK references, records immutable receipts and closes only its own fixture under strict guards. This replaces Python bootstrap for parameter qualification without claiming
new_designparity. No startup autoload or network endpoint. - Native blank
new_design. Validate request and bounds, reserve journal/result/identity capacity, then create once outside Command events under a checked neutral-command guard. Adopt the exact returned reference, verify parent/product/type/intent/unsaved state, and retain requested-name metadata without renaming. Unsupportedboxmust refuse before admission; transaction capability remains unqualified until ported. Expose the narrower versioned native contract. - Owned discard and exact-ID activation. Separate explicit journaled operations; no active/name fallback and no bulk close. A live non-transferable ownership receipt is required for discard. Activation accepts exact current identity and a checked expected active identity. Restoring the previous active document is an explicit bounded step whose failure cannot obscure successful close.
- Legacy completion. Port transaction probe and bounded recovery witness, box construction and complete inspection; then independently qualify general save/close semantics. Do not block useful blank/native parameter tests on this larger parity step.
Ownership and identity changes
identity::Registry::with_document currently verifies that a leased member remains valid after its closure. It is suitable for parameter work and activation, but successful close deliberately invalidates its target. Do not bypass this check or close through that API and treat the resulting registry fault as success. Add dedicated owner-thread creation/adoption and retirement transitions with the same exclusive reentrancy guard.
Proposed internal types, not committed API:
CreationReservation: non-Clone, bound to registry allocation and epoch; reserves one serial/member slot, one owned-scratch entry, and bounded receipt storage before any SDK effect. If the 256-document registry or smaller scratch limit is full, fail beforeadd. Abandoning a pre-effect reservation can release capacity; post-effect uncertainty cannot evict it.CreationAttempt: reports whether invocation began, call acknowledgement, and an optional retained exact SDK lease separately from inspection errors. Preallocate the C++ lease holder beforeadd. If a valid handle is returned, store it before fallible JSON/string/readback work; never let a plainResult<Handle>discard the only ownership proof on later failure.OwnedScratch: private live authority bound to registry epoch, journal session/create operation/request digest, exact adopted ID and retained SDK reference, original native name, initial saved/data-file observations, and supported cleanup-profile witness. Serialized receipts expose evidence, never a reconstructible native handle or authority.CloseAttempt: consumes one effect permission, invokes exact-objectclose(false)at most once, then verifies invalidity and absence in a bounded complete roster. Successful retirement removes that ID permanently. Ambiguity retains a quarantined ownership entry and forbids another close invocation under that attempt.
Creation's returned reference must match exactly one member of a complete stable post-create roster by SDK equality. Never adopt the current active object, a same-name object, a matching creationId, or the only list difference. Reserve the serial before invocation; keep returned references quarantined if membership/metadata verification fails. A partial roster is not evidence of absence. Nested callbacks, allocation failures, serial overflow, duplicates and release failures retain conservative fault behavior; no SDK handle crosses to the worker thread.
Public scratch acquisition requires both a coherent durable current-session successful creation receipt and the live ownership entry. A failed/unknown creation may retain a private recovery lease for diagnosis; it does not become a normal public scratch capability. Across restart, history remains readable but old scratch ownership expires. A fresh runtime must not re-adopt or close old documents using journal contents or attributes alone.
Guards and outcomes
Before both preflight and actual create/close, check owner thread, SDK validity, bounded complete roster, and command state. Dispatch from a non-Command callback; accept only an empirically qualified exact neutral command ID, initially SelectCommand, with a successful getter. Unknown/empty IDs need separate qualification rather than being silently mapped to idle. If launch from Scripts Manager reports another command, refuse. A command-start event fence may strengthen this guard later, but event tracking cannot retroactively prove an already-running transaction absent. No automatic abort, doEvents, Undo, or PTransaction around lifecycle calls.
Owned discard requires exact live ownership, exact active object, unchanged original unnamed native name, isSaved=false, null dataFile with successful getter, and a supported expected-content witness. creationId is an additional consistency check only. A renamed/saved/replaced object or failed getter refuses before close. Never select a sibling object when a guard fails. If closing the last document creates a replacement Untitled, record that distinct unowned identity and leave it alone.
The first cleanup profile should be deliberately small: one component, no geometry/sketches/occurrences/features/derived or external resources, no other live preview lease, and bounded numeric user parameters. The product cleanup witness must combine root revision, complete supported parameter state/default units, and explicit empty-model/resource checks, recorded after each owned mutation. Refuse unknown or unsupported state. The r7 parameter digest alone does not prove that arbitrary user modeling work is absent; if coverage cannot be established, leave edited scratch discard unavailable instead of pretending the digest is complete. The isolated test fixture permits the expressly authorized parameter edits and clearly reports its narrower cleanup profile.
| Observation | Report and next action |
|---|---|
| Guard/deadline/capacity refusal before SDK invocation | Not executed; no document effect. |
add invoked but throws/returns null, or identity cannot be retained |
Unknown; retain available evidence, stop creation admission, never create again automatically. |
| Exact created reference retained but readback/adoption fails | Unknown with private quarantined lease; no normal public ownership claim and no guessed rollback. |
| Creation fully observed, terminal persistence/clock fails | Observed nondurable result; keep exact lease and evidence, reconciliation required. No replay. |
| Close returns true and exact object is invalid and absent in a complete roster | Observed closed; retire ID, retain close receipt, then attempt any separately authorized exact prior activation. |
| Close returns false/throws or contradicts readback | Unknown, including a false acknowledgement with apparent absence; retain raw acknowledgement and actual observation, no second close. |
| Activation returns true and actual active object equals requested exact reference | Observed activation success. Same-name equality is insufficient. |
| Activation is declined, throws, or readback fails | Report ambiguous/refused activation separately; do not try another object or conceal an already-observed create/close. |
Restoration must not steal focus from a document the user activated meanwhile: restore only if the currently active identity still matches the workflow's expected state and the retained prior object is still a unique current member. If that condition changed, leave the user's active document alone and report restoration skipped. Never re-open a closed previous document.
Journal and shutdown integration
Retain the current coordinator sequence: bounded canonical request → durable admission/dispatch → read-only preflight → durable start → second owner-thread execution with guards repeated → observe result before terminal persistence. Reserve worst-case result bytes before effects. Creation has no pre-existing target; its start record must honestly contain operation kind, baseline/current active identity and reservation evidence, rather than inventing a target document. All owned data returned to the worker is bounded and Send.
Creation, close and activation have separate operation identities. Repeated same-ID/same-digest requests read status; conflicts refuse, and neither grants a new effect permission. The observer survives HTTP timeout. Use retained unknown handling for post-invocation ambiguity; do not persist an ordinary failed terminal that implies a known outcome. Durable terminal records remain authoritative. Old-session nonterminal records stay interrupted/unknown, and process-local ownership cannot be reconstructed from them. Retention/SQLite failure prevents new effects, without silently discarding already-observed receipts.
SDK lease release is not Document.close. Runtime stop must not close all owned or user documents implicitly. Complete explicit scratch cleanup while the service/SDK dispatcher is alive, or report the fixture as still open. Preserve existing shutdown order and uncertainty rules: stop admission, settle/cancel queue work safely, join owned workers without a main-thread callback dependency, unregister the custom event once, release all registry leases once on the owner thread, then close the SDK context. In-flight/reentrant callbacks must refuse unsafe stop. If event removal or reference release is unconfirmed, retain code/callback storage and report reconciliation; do not unload underneath retained SDK pointers or retry uncertain deletion. Add owned-resource counts/disposition to stop receipts without conflating “references released” with “documents discarded.”
Concrete qualification cases
| Layer | Required behavioral cases |
|---|---|
| Pure Rust lifecycle decisions | Reject wrong thread/command/epoch/receipt, saved/renamed/replaced targets, missing prior document, active identity drift, stale witness, nonempty/unsupported model; parameter-only allowed profile; bounds and reservation exhaustion before effect. |
| Instrumented SDK backend | Exact returned-object adoption among duplicate names/creation IDs; add changes active document unexpectedly; null/throw after effect; post-create enumeration failure; nested callbacks; serial overflow; close false/throw with both still-open and actually-closed outcomes; false activation with same-name sibling active. Count each mutator invocation and each lease release. |
| Journal/fault boundary | Failure before admission/start produces zero SDK mutations; failed terminal write/clock retains created/closed observation; lost acknowledgement never retries; duplicate/conflicting operation IDs; HTTP deadline followed by late SDK result; fresh-session historical records cannot claim ownership. |
| Cleanup witness | User adds geometry, component, sketch, custom graphics, external/derived resources, saves, renames, changes a parameter, or switches active document between the two SDK hops: unsafe close is absent from call log. Parameter test fixture cleanup accepts only its documented bounded profile. |
| Independent Rust verifier | Drive public lifecycle contract, compare before/after exact object sets, retain all unrelated documents, verify same-name decoys untouched, preserve immutable receipt bytes on repeated start/stop, and verify no extra document after duplicate creation request. Product builder tests alone are insufficient. |
| Windows SDK fixture | Manually load exact frozen DLL; create one never-saved unnamed fixture; verify type/intent/parent/identity and unchanged original documents; run the parameter campaign; close the retained fixture once and verify absence; restore exact prior active object. No rename/cloud save/command cancellation/capture. Unknown command/refusal stops the run. |
| Stop/unload | Pending-before-claim cancellation, in-flight observation settlement, nested stop refusal, uncertain close/resource release, stopped HTTP admission, exact event removal, all owner-thread references released, no automatic document deletion, fresh runtime cannot reuse receipt authority. |
Release evidence must distinguish offline model tests, Windows typed SDK compilation, isolated fixture execution, product lifecycle execution, and complete legacy parity. The fixture is temporary qualification tooling; it does not count as a released new_design, general close, or animation/presentation lifecycle feature.
# Native document lifecycle port
Status: design audit, 2026-10-14. Product source is unchanged by this document. The next useful slice is native blank-design creation with exact identity adoption, explicit owned-scratch discard, and exact-ID activation. Optional box construction, transaction probing, general document close/save, and full legacy inspection remain separate qualification obligations. A small isolated Rust test-fixture add-in can qualify SDK lifecycle behavior before exposing these product operations.
## Source and contract audit
Legacy paths below are relative to `../exploded-preview-preparation/runtime-dev9-build-r1/source/addin/AdomBridge/`.
| Source | Actual behavior and port consequence |
| --- | --- |
| `commands/mechanical/operations.py:97` | `new_design` validates a requested label (default `Adom mechanical`, 1–120 characters) and optional positive finite width/height/depth in mm. It retains the previous active object, calls `documents.add(FusionDesignDocumentType)`, resolves that document's Design product, and sets parametric design type. |
| Same function | If the session transaction backend is unverified, creation runs the mutation/abort/commit/recovery probe in the new design. Optional box creates three driving user parameters, a dimensioned XY rectangle, and an extrusion. It recomputes/checks health and returns full legacy inspection. Blank creation alone does not implement these semantics. |
| Same function | Requested label is an `AdomMechanical/requestedName` root attribute, not `Document.name`. Failure cleanup checks the retained document is unsaved and starts with `Untitled`, invokes `close(False)` without checking its Boolean, then tests validity. Previous-document activation ignores its Boolean and identity readback. Preserve the useful naming precaution; replace these weak outcome checks. |
| `commands/close_document.py:16,82` | General close selects the first exact name or the active document; it attempts to terminate/abort an active command, executes SelectCommand and pumps events. For a modified cloud document it may save a new version even when `save=false`, then ignores the close Boolean. Do not carry those hidden effects into owned-scratch cleanup. |
| `commands/close_document.py:176` | Bulk close snapshots the original list because Fusion may create a replacement Untitled when the last document closes. It has independent skip/force/save rules. The native scratch operation closes exactly one retained object and never loops on document count. |
| `commands/document_info.py:176` | Activation accepts substring name/type/data-file filters, favors exact names, and may try another matching candidate after failure. Its final verification compares active names; a failed active-name getter can leave verification incomplete. Native activation uses one current registry ID and SDK object equality, with one invocation. |
| `commands/mechanical/exploded_preview.py:94,146` | Preview adoption requires a coherent current-session succeeded `new_design` journal receipt with matching request digest/target and unsaved state, plus exact live retained object, active state, blank-model witness, and an exclusive session lease. History never reconstructs native ownership after reload. Preserve this separation of durable creation evidence from a live capability. |
| `mechanical/schema.json:/new_design` | Promises an unnamed unsaved parametric hybrid design and optional parameter-driven box. New native capabilities must describe their implemented subset and keep `legacyParity:false` until the missing paths are qualified. |
Installed SDK headers were read under `C:/Users/drew/AppData/Roaming/Autodesk/Autodesk Fusion 360/API/CPP/include`. The following official references were checked on 2026-10-14:
- [Documents.add](https://help.autodesk.com/cloudhelp/ENU/Fusion-360-API/files/core_Documents_add.htm): creation returns the created document, currently requires visible creation, and is unsupported within Command-related events/transactions. The [official creation sample](https://help.autodesk.com/cloudhelp/ENU/Fusion-360-API/files/DocumentCreation_Sample.htm) says default creation is hybrid; verify actual `Design.designIntent` rather than inventing `NamedValues` option keys.
- [Document.close](https://help.autodesk.com/cloudhelp/ENU/Fusion-360-API/files/core_Document_close.htm): close has the same Command restriction, returns a Boolean, and `saveChanges=true` can prompt. `false` is the documented discard choice. Legacy comments and the local no-modal skill record narrower empirical prompt hazards for named unsaved documents; those are local qualification constraints, not an extra official API guarantee.
- [Document.activate](https://help.autodesk.com/cloudhelp/ENU/Fusion-360-API/files/core_Document_activate.htm): changes the active document and returns a Boolean. The result requires exact active-object readback.
- [UserInterface.activeCommand](https://help.autodesk.com/cloudhelp/ENU/Fusion-360-API/files/core_UserInterface_activeCommand.htm) exposes a command ID. No documented global “transaction open” getter was found in the examined headers. A custom event reaching the main thread is not proof that create/close is allowed.
- `Core/Application/Document.h:50–76,148–157`: names may be changed before first save; `creationId`, names and saved/modified flags are observations, not unique ownership capabilities. Copies may share creation metadata.
- `Fusion/Fusion/Design.h:72–79,333–348`: design type and design intent are distinct. Changing an existing parametric design to direct destroys history. Set type only on the exact newly returned design and read it back.
- `Fusion/Components/Component.h:295–298`: component revision changes with component changes. It is not a documented whole-Design revision; the current `parameters-v1` projection is explicitly scoped and cannot be relabeled a complete document-content guard.
Apply [fusion-no-modal-dialogs](/home/adom/.codex/skills/fusion-no-modal-dialogs/SKILL.md): retain the untouched native scratch name, never silently save to make close possible, refuse an unknown command or prompt-prone target before invocation. Do not add dialog sweeping, automatic command termination, event pumping, or screenshot loops.
## Small implementation slices
1. **Isolated lifecycle fixture, not a product capability.** A manually loaded Rust test DLL creates one blank unsaved parametric hybrid design, retains exact created/prior SDK references, records immutable receipts and closes only its own fixture under strict guards. This replaces Python bootstrap for parameter qualification without claiming `new_design` parity. No startup autoload or network endpoint.
2. **Native blank `new_design`.** Validate request and bounds, reserve journal/result/identity capacity, then create once outside Command events under a checked neutral-command guard. Adopt the exact returned reference, verify parent/product/type/intent/unsaved state, and retain requested-name metadata without renaming. Unsupported `box` must refuse before admission; transaction capability remains unqualified until ported. Expose the narrower versioned native contract.
3. **Owned discard and exact-ID activation.** Separate explicit journaled operations; no active/name fallback and no bulk close. A live non-transferable ownership receipt is required for discard. Activation accepts exact current identity and a checked expected active identity. Restoring the previous active document is an explicit bounded step whose failure cannot obscure successful close.
4. **Legacy completion.** Port transaction probe and bounded recovery witness, box construction and complete inspection; then independently qualify general save/close semantics. Do not block useful blank/native parameter tests on this larger parity step.
## Ownership and identity changes
`identity::Registry::with_document` currently verifies that a leased member remains valid after its closure. It is suitable for parameter work and activation, but successful close deliberately invalidates its target. Do not bypass this check or close through that API and treat the resulting registry fault as success. Add dedicated owner-thread creation/adoption and retirement transitions with the same exclusive reentrancy guard.
Proposed internal types, not committed API:
- `CreationReservation`: non-Clone, bound to registry allocation and epoch; reserves one serial/member slot, one owned-scratch entry, and bounded receipt storage before any SDK effect. If the 256-document registry or smaller scratch limit is full, fail before `add`. Abandoning a pre-effect reservation can release capacity; post-effect uncertainty cannot evict it.
- `CreationAttempt`: reports whether invocation began, call acknowledgement, and an optional retained exact SDK lease separately from inspection errors. Preallocate the C++ lease holder before `add`. If a valid handle is returned, store it before fallible JSON/string/readback work; never let a plain `Result<Handle>` discard the only ownership proof on later failure.
- `OwnedScratch`: private live authority bound to registry epoch, journal session/create operation/request digest, exact adopted ID and retained SDK reference, original native name, initial saved/data-file observations, and supported cleanup-profile witness. Serialized receipts expose evidence, never a reconstructible native handle or authority.
- `CloseAttempt`: consumes one effect permission, invokes exact-object `close(false)` at most once, then verifies invalidity and absence in a bounded complete roster. Successful retirement removes that ID permanently. Ambiguity retains a quarantined ownership entry and forbids another close invocation under that attempt.
Creation's returned reference must match exactly one member of a complete stable post-create roster by SDK equality. Never adopt the current active object, a same-name object, a matching `creationId`, or the only list difference. Reserve the serial before invocation; keep returned references quarantined if membership/metadata verification fails. A partial roster is not evidence of absence. Nested callbacks, allocation failures, serial overflow, duplicates and release failures retain conservative fault behavior; no SDK handle crosses to the worker thread.
Public scratch acquisition requires both a coherent durable current-session successful creation receipt and the live ownership entry. A failed/unknown creation may retain a private recovery lease for diagnosis; it does not become a normal public scratch capability. Across restart, history remains readable but old scratch ownership expires. A fresh runtime must not re-adopt or close old documents using journal contents or attributes alone.
## Guards and outcomes
Before both preflight and actual create/close, check owner thread, SDK validity, bounded complete roster, and command state. Dispatch from a non-Command callback; accept only an empirically qualified exact neutral command ID, initially `SelectCommand`, with a successful getter. Unknown/empty IDs need separate qualification rather than being silently mapped to idle. If launch from Scripts Manager reports another command, refuse. A command-start event fence may strengthen this guard later, but event tracking cannot retroactively prove an already-running transaction absent. No automatic abort, `doEvents`, Undo, or `PTransaction` around lifecycle calls.
Owned discard requires exact live ownership, exact active object, unchanged original unnamed native name, `isSaved=false`, null `dataFile` with successful getter, and a supported expected-content witness. `creationId` is an additional consistency check only. A renamed/saved/replaced object or failed getter refuses before `close`. Never select a sibling object when a guard fails. If closing the last document creates a replacement Untitled, record that distinct unowned identity and leave it alone.
The first cleanup profile should be deliberately small: one component, no geometry/sketches/occurrences/features/derived or external resources, no other live preview lease, and bounded numeric user parameters. The product cleanup witness must combine root revision, complete supported parameter state/default units, and explicit empty-model/resource checks, recorded after each owned mutation. Refuse unknown or unsupported state. The r7 parameter digest alone does not prove that arbitrary user modeling work is absent; if coverage cannot be established, leave edited scratch discard unavailable instead of pretending the digest is complete. The isolated test fixture permits the expressly authorized parameter edits and clearly reports its narrower cleanup profile.
| Observation | Report and next action |
| --- | --- |
| Guard/deadline/capacity refusal before SDK invocation | Not executed; no document effect. |
| `add` invoked but throws/returns null, or identity cannot be retained | Unknown; retain available evidence, stop creation admission, never create again automatically. |
| Exact created reference retained but readback/adoption fails | Unknown with private quarantined lease; no normal public ownership claim and no guessed rollback. |
| Creation fully observed, terminal persistence/clock fails | Observed nondurable result; keep exact lease and evidence, reconciliation required. No replay. |
| Close returns true and exact object is invalid and absent in a complete roster | Observed closed; retire ID, retain close receipt, then attempt any separately authorized exact prior activation. |
| Close returns false/throws or contradicts readback | Unknown, including a false acknowledgement with apparent absence; retain raw acknowledgement and actual observation, no second close. |
| Activation returns true and actual active object equals requested exact reference | Observed activation success. Same-name equality is insufficient. |
| Activation is declined, throws, or readback fails | Report ambiguous/refused activation separately; do not try another object or conceal an already-observed create/close. |
Restoration must not steal focus from a document the user activated meanwhile: restore only if the currently active identity still matches the workflow's expected state and the retained prior object is still a unique current member. If that condition changed, leave the user's active document alone and report restoration skipped. Never re-open a closed previous document.
## Journal and shutdown integration
Retain the current coordinator sequence: bounded canonical request → durable admission/dispatch → read-only preflight → durable start → second owner-thread execution with guards repeated → observe result before terminal persistence. Reserve worst-case result bytes before effects. Creation has no pre-existing target; its start record must honestly contain operation kind, baseline/current active identity and reservation evidence, rather than inventing a target document. All owned data returned to the worker is bounded and `Send`.
Creation, close and activation have separate operation identities. Repeated same-ID/same-digest requests read status; conflicts refuse, and neither grants a new effect permission. The observer survives HTTP timeout. Use retained unknown handling for post-invocation ambiguity; do not persist an ordinary failed terminal that implies a known outcome. Durable terminal records remain authoritative. Old-session nonterminal records stay interrupted/unknown, and process-local ownership cannot be reconstructed from them. Retention/SQLite failure prevents new effects, without silently discarding already-observed receipts.
SDK lease release is not `Document.close`. Runtime stop must not close all owned or user documents implicitly. Complete explicit scratch cleanup while the service/SDK dispatcher is alive, or report the fixture as still open. Preserve existing shutdown order and uncertainty rules: stop admission, settle/cancel queue work safely, join owned workers without a main-thread callback dependency, unregister the custom event once, release all registry leases once on the owner thread, then close the SDK context. In-flight/reentrant callbacks must refuse unsafe stop. If event removal or reference release is unconfirmed, retain code/callback storage and report reconciliation; do not unload underneath retained SDK pointers or retry uncertain deletion. Add owned-resource counts/disposition to stop receipts without conflating “references released” with “documents discarded.”
## Concrete qualification cases
| Layer | Required behavioral cases |
| --- | --- |
| Pure Rust lifecycle decisions | Reject wrong thread/command/epoch/receipt, saved/renamed/replaced targets, missing prior document, active identity drift, stale witness, nonempty/unsupported model; parameter-only allowed profile; bounds and reservation exhaustion before effect. |
| Instrumented SDK backend | Exact returned-object adoption among duplicate names/creation IDs; add changes active document unexpectedly; null/throw after effect; post-create enumeration failure; nested callbacks; serial overflow; close false/throw with both still-open and actually-closed outcomes; false activation with same-name sibling active. Count each mutator invocation and each lease release. |
| Journal/fault boundary | Failure before admission/start produces zero SDK mutations; failed terminal write/clock retains created/closed observation; lost acknowledgement never retries; duplicate/conflicting operation IDs; HTTP deadline followed by late SDK result; fresh-session historical records cannot claim ownership. |
| Cleanup witness | User adds geometry, component, sketch, custom graphics, external/derived resources, saves, renames, changes a parameter, or switches active document between the two SDK hops: unsafe close is absent from call log. Parameter test fixture cleanup accepts only its documented bounded profile. |
| Independent Rust verifier | Drive public lifecycle contract, compare before/after exact object sets, retain all unrelated documents, verify same-name decoys untouched, preserve immutable receipt bytes on repeated start/stop, and verify no extra document after duplicate creation request. Product builder tests alone are insufficient. |
| Windows SDK fixture | Manually load exact frozen DLL; create one never-saved unnamed fixture; verify type/intent/parent/identity and unchanged original documents; run the parameter campaign; close the retained fixture once and verify absence; restore exact prior active object. No rename/cloud save/command cancellation/capture. Unknown command/refusal stops the run. |
| Stop/unload | Pending-before-claim cancellation, in-flight observation settlement, nested stop refusal, uncertain close/resource release, stopped HTTP admission, exact event removal, all owner-thread references released, no automatic document deletion, fresh runtime cannot reuse receipt authority. |
Release evidence must distinguish offline model tests, Windows typed SDK compilation, isolated fixture execution, product lifecycle execution, and complete legacy parity. The fixture is temporary qualification tooling; it does not count as a released `new_design`, general close, or animation/presentation lifecycle feature.