Build a Python project that generates and maintains a token-sparse, agent-friendly layer on top of the Autodesk Fusion API.
The project must satisfy five requirements at the same time:
- Be easy for coding agents to read and write.
- Reduce token count and ceremony for common modeling tasks.
- Preserve full practical compatibility with the existing Fusion API.
- Be updateable when Autodesk publishes new API releases.
- Be usable both in ordinary Fusion scripts and in add-ins.
This plan assumes the implementation language is Python and that the generated runtime will execute inside Fusion's embedded Python environment. Build tooling may use external Python packages, but the runtime library that ships into Fusion should have zero third-party runtime dependencies.
This document is written for a coding agent that will execute the work locally.
Do not hand-wrap the entire Autodesk API.
Instead, implement a generator-driven system with four layers:
-
Official corpus ingestion
- Use the official
AutodeskFusion360/FusionAPIReferencerepository as the source corpus. - Use its Python definitions first, C++ headers second, and docs third.
- Use the official
-
Normalized intermediate representation
- Build a machine-readable API IR that represents classes, methods, properties, enums, inheritance, samples, versions, and doc metadata.
-
Generated metadata and compatibility layer
- Generate registries, symbol maps, enum aliases, version diffs, and wrapper dispatch tables from the IR.
-
Handwritten ergonomic runtime with generated policy inputs
- Keep only a small handwritten runtime.
- Generate the large, repetitive pieces.
- Apply a small rule set to create the compact user-facing API.
The generator is the product. The wrapper library is a generated artifact plus a thin handwritten core.
The implementation must obey the following:
When there is a conflict or ambiguity, use this precedence order:
Fusion_API_Python_Reference/defs/Fusion_API_CPP_Reference/include/Fusion_API_Documentation/files/orprocessed_docs/md/if available- Sample code repositories only as examples or regression fixtures, never as the schema source
The compact layer must never block access to the raw Autodesk API.
Every wrapper object must support:
.rawto access the original Autodesk object- pass-through access to raw camelCase members where practical
- use of raw Autodesk objects as arguments to compact helpers
- use of compact wrappers as arguments to raw Autodesk methods
If a compact helper does not exist for some API area, the user must still be able to reach the official API immediately.
The runtime package that is copied into Fusion must use only the Python standard library plus adsk.*.
All parsing, code generation, HTML conversion, and indexing dependencies belong in build tooling only.
Never treat bare numeric literals as document units.
For the compact layer:
- bare numbers mean Fusion internal units only
- strings mean Fusion expressions
- explicit unit helpers such as
u.mm(5)andu.deg(30)are preferred
This rule is non-negotiable.
Do not hide the modeling target.
Compact APIs must make the target component or design context explicit. Do not create geometry implicitly in some guessed "active" component.
Never manually edit generated files.
All manual behavior must live in handwritten runtime modules or in rule files consumed by the generator.
The minimum acceptable first release is a generated library that supports this workflow:
import fusion_sparse as fx
def run(_):
design = fx.new_design()
root = design.root
sk = root.sketch("xy")
sk.circle((0, 0), r="20 mm")
root.extrude(sk.profile(), "50 mm", op="new_component")And also this more explicit builder-style workflow:
import fusion_sparse as fx
def run(_):
design = fx.new_design()
root = design.root
sk = root.sketch("xy")
sk.rect((0, 0), (40, 20))
ext = (
root.extrude(sk.profile(), op="new_body")
.one_side("10 mm", direction="positive")
.build()
)The first release does not need to provide compact wrappers for the full API surface. It does need to provide complete metadata coverage and raw fallback coverage, plus a high-quality compact layer for the most important modeling operations.
Measure success explicitly.
For common workflows, compare official-style code to compact-wrapper code.
Create benchmark pairs for:
- create application context and new design document
- create sketch on default plane
- draw circle
- draw rectangle
- extrude simple new body
- extrude new component
- set one-side extent with builder path
For each pair compute:
- character count
- line count
- token count using a deterministic tokenizer script
- number of Autodesk enum references
- number of
adsk.symbol occurrences
Initial targets:
- 40 percent or greater reduction in character count for common workflows
- 50 percent or greater reduction in line count for common workflows
- 50 percent or greater reduction in
adsk.symbol occurrences for common workflows - no loss of capability for those workflows
- 100 percent of wrapper objects expose
.raw - unsupported raw API access works without monkey patching or manual conversions
- all compact helper arguments accept either compact wrappers or raw Autodesk objects where sensible
When the corpus is refreshed:
- IR diff is produced automatically
- generator output is deterministic
- release report highlights new symbols, changed signatures, added enums, and possible compatibility risks
- at least one smoke script still runs in Fusion after regeneration
- corpus ingestion from
FusionAPIReference - parser pipeline and IR
- deterministic code generation
- runtime core
- compact layer for design and solid-modeling basics
- tests, smoke scripts, and benchmarks
- release diff tooling
- optional add-in test harness
- optional MCP-driven integration harness if available locally
Do not start with these:
- full CAM compact wrappers
- full UI command abstraction for every command feature
- custom features
- complete custom graphics abstraction
- generative art DSL
- full assembly authoring abstraction
- perfect automation of Fusion GUI interactions
These can come later. The first goal is a robust generated foundation plus a thin, useful compact layer.
Use the official Autodesk repository as the primary local corpus:
AutodeskFusion360/FusionAPIReference
Treat its contents as follows:
-
Fusion_API_Python_Reference/defs/- primary source for Python-facing names, signatures, return annotations, and type hints
-
Fusion_API_CPP_Reference/include/- verifier for enums, overloads, missing type detail, inheritance, and method prototypes
-
Fusion_API_Documentation/files/- semantic layer for descriptions, sections, examples, sample links, version metadata, and workflow hints
-
processed_docs/md/- if present, use as preferred cleaned prose source before raw HTML
Use Autodesk GitHub sample repositories and FusionMCPSample only as:
- regression fixtures
- example call chains to compress
- optional integration test harness inspiration
Do not infer API completeness from them.
The reference corpus is licensed separately from the library code.
Implementation rule:
- do not ship Autodesk HTML documentation or large copied doc text inside the runtime package
- generated metadata shipped with runtime should be limited to what is necessary for operation
- keep the full corpus as an external dev-time input
- if redistributing generated metadata derived from Autodesk documentation, do a separate licensing review
The system has three major code areas.
This lives outside Fusion and can use external dependencies.
Responsibilities:
- load corpus
- parse Python defs
- parse C++ headers
- parse docs
- merge into IR
- apply manual override rules
- generate metadata and code
- diff current API against previous snapshots
- generate docs for humans and agents
This is the package copied into Fusion.
Responsibilities:
- wrap Autodesk objects
- adapt arguments and return values
- provide explicit context helpers
- provide unit-safe values and transient geometry helpers
- expose compact wrapper classes
- preserve raw access
- load generated registries
Responsibilities:
- smoke scripts runnable directly in Fusion
- add-in bundle for command testing
- optional MCP-driven automation for screenshot or script execution
Create the repository with this structure.
fusion_sparse/
pyproject.toml
README.md
implementation_plan.md
LICENSE
.gitignore
docs/
compact_reference.md
raw_mapping.md
corpus/
README.md
FusionAPIReference/ # optional git submodule or local checkout, ignored if absent
corpus.lock.json
rules/
aliases.yaml
compact_exports.yaml
compact_policy.yaml
compact_reference.yaml
family_overrides.yaml
enum_aliases.yaml
exclusions.yaml
doc_overrides.yaml
wrapper_dispatch.yaml
tools/
__init__.py
cli.py
corpus_loader.py
parse_python_defs.py
parse_cpp_headers.py
parse_docs.py
build_ir.py
apply_rules.py
generate_metadata.py
build/
ir/
generated/
reports/
src/
fusion_sparse/
__init__.py
runtime/
adapter.py
refs.py
context.py
values.py
geom.py
enums.py
errors.py
_adsk.py
compact/
__init__.py
app.py
design.py
component.py
sketch.py
extrude.py
generated/
__init__.py
compact_policy.py
compact_surface.py
public_api.py
enum_index.py
wrapper_dispatch.py
release_info.py
tests/
unit/
golden/
integration/
fusion_scripts/
fusion_addin/
benchmarks/
baselines/
compact/
examples/
simple_extrude.py
sketch_playground.py
context_debug.py
fusion/
scripts/
FusionSparseSmoke/
addins/
FusionSparseWorkbench/
Notes:
build/is generated and can be cleaned.src/fusion_sparse/generated/is generated but committed once the project stabilizes.fusion/contains test bundles that can be linked into Fusion's Scripts and Add-Ins UI.
Develop the codebase as a normal Python project outside Fusion, but deploy testable artifacts into Fusion-compatible script and add-in bundles.
Use a smoke script bundle like this:
fusion/scripts/FusionSparseSmoke/
FusionSparseSmoke.py
FusionSparseSmoke.manifest
lib/
fusion_sparse/
The script entry file should be tiny and only import the library and call a test function.
Use an add-in bundle like this, following the Autodesk Python add-in template shape:
fusion/addins/FusionSparseWorkbench/
FusionSparseWorkbench.py
FusionSparseWorkbench.manifest
config.py
commands/
smoke_command/
__init__.py
entry.py
resources/
lib/
fusion_sparse/
fusion360utils/
Important implementation rules:
- Keep the add-in top-level
.pyfile minimal, mirroring the official template pattern withrun(context)andstop(context). - Put most test command logic under
commands/.../entry.py. - Do not make the library depend on
fusion360utils; that dependency belongs only to the optional add-in harness. - Provide a
tools/sync_to_fusion.pyscript that copies or syncs the runtime package intolib/fusion_sparse/for both the smoke script and the workbench add-in. - Prefer linked script and add-in folders in Fusion during development so the local repo remains the editable source of truth.
Implement tools/sync_to_fusion.py with these capabilities:
- locate target Fusion script/add-in directories from configuration or CLI flags
- copy
src/fusion_sparse/into targetlib/fusion_sparse/ - optionally copy smoke scripts and workbench add-in files
- remove stale generated files in target bundles before syncing
- preserve only source
.pyfiles and required metadata, not.pyc - print a clear summary of what was synced
- After sync, Fusion can see the linked script or add-in.
- The smoke script can import
fusion_sparsefrom the local repo copy. - The workbench add-in follows the official Autodesk template structure closely enough that a Fusion developer immediately recognizes it.
Use these build-time libraries unless the local environment strongly suggests an equivalent:
libcstfor parsing Python definitions and stubsbeautifulsoup4andlxmlfor HTML parsingpyyamlfor rule filesjinja2for deterministic code generation templatespydanticor dataclasses for IR modelingpytestfor unit tests- optional
richortyperfor CLI ergonomics
Runtime inside Fusion must use:
- standard library only
adsk.coreadsk.fusionadsk.cam
No third-party runtime dependencies.
Build tooling can target a normal desktop Python version.
Runtime code must stay conservative and compatible with Fusion's embedded Python. Since Fusion updated embedded Python from 3.12 to 3.14 in January 2026, do not rely on shipping .pyc files or version-specific bytecode artifacts. Ship source .py files only.
Create a stable repo skeleton and execution model before touching the parser.
- Create repository structure shown above.
- Add
pyproject.tomlwith build and dev dependencies. - Add
Makefileor task aliases if desired, but do not require it. - Add
README.mdwith one-paragraph project summary. - Add
rules/placeholder files with comments. - Add
tools/cli.pyentry point with commands:build-irgeneratediffmeasuresync-fusion
- Add
corpus/README.mdexplaining how to place or submodule the Autodesk corpus. - Add
corpus/corpus.lock.jsonschema now even if empty.
- Repo installs in a local virtual environment.
python -m tools.cli --helpworks.- Empty build commands fail clearly with missing corpus instructions.
Load the local Autodesk corpus deterministically and record exactly what was used.
- Implement
tools/corpus_loader.py. - Detect repository root for
FusionAPIReference. - Verify presence of:
Fusion_API_Python_Reference/defsFusion_API_CPP_Reference/includeFusion_API_Documentation/files
- Detect optional:
processed_docs/mdtools/generate_index.pyllms.txt
- Record a corpus manifest:
- source root path
- commit hash if available from
.git - timestamp
- discovered paths
- counts of files per source type
- Write
corpus/corpus.lock.json. - Add a build report at
build/reports/corpus_summary.md.
- Build reports list the discovered corpus and file counts.
- Failure modes are explicit if required directories are missing.
- Lockfile is deterministic.
Extract the Python-facing API surface from Autodesk's defs.
Use libcst or an equally robust parser. Do not depend on fragile regex for Python defs.
For each module, class, function, method, property, enum-like constant, and assignment:
- module path
- namespace inferred from module path
- class name
- fully qualified symbol name
- kind: module, class, method, property, function, enum, constant
- decorators
- parameter list
- parameter annotations
- default values as strings
- return annotations
- docstring if present
- staticmethod/classmethod/property status
- inheritance bases
- source path and line spans
- Support both
.pyand.pyistyle syntax. - Preserve unknown type names as raw strings.
- Do not try to resolve every import at first.
- Do preserve enough module information to reconstruct fully qualified names.
Write:
build/ir/python_symbols.json
- Can parse the corpus without crashing.
- Produces symbols for core sample classes such as
Application,Design,Component,Sketch,ExtrudeFeatures,ValueInput. - Unit tests cover representative parser cases.
Use headers to verify and enrich types, not to replace the Python defs parser.
Start simple. Parse only what is high value:
- enum names and values
- class declarations
- inheritance
- method signatures where they are easy to extract
- static methods
- header-defined namespaces
Do not block the project on full C++ parsing.
Start with a conservative regex or line-oriented parser because this is a verifier pass, not the primary source. If local tooling already has a workable C++ parser, use it, but do not make that a hard dependency.
- enum name
- enum members and numeric values if present
- class name
- namespace
- method name
- return type
- parameter types and names
- static flag if inferable
- source header path
Write:
build/ir/cpp_symbols.jsonbuild/ir/cpp_enums.json
- Enum extraction works for
DocumentTypes,FeatureOperations,ExtentDirections, and a few other core enums. - Header parsing enriches missing type detail where Python defs are thin.
- Parser never crashes the build if a header is not understood; it logs and continues.
Enrich the IR with prose, examples, version info, section structure, and workflow hints.
Use processed_docs/md if present. Otherwise parse the HTML under Fusion_API_Documentation/files.
From each page, when available:
- page title
- page kind inferred from title or file stem:
- object
- method
- property
- sample
- user-manual topic
- description section
- syntax section
- parameters table
- return value section
- samples list
- version section
- headings hierarchy
- code blocks
- related links
- owner object
- namespace
- header file
- file stem
- Normalize
Application_get.htmto symbol keyApplication.get - Normalize
ValueInput_createByString.htmtoValueInput.createByString - Preserve sample page references
- Strip navigation/footer boilerplate aggressively
- Keep code blocks and parameter tables intact
Write:
build/ir/doc_pages.jsonbuild/ir/doc_symbol_links.json
- Can resolve docs for:
Application.getDocuments.addValueInput.createByStringValueInput.createByRealExtrudeFeatures.addSimpleExtrudeFeatures.createInput
- Version metadata is captured when present.
- Sample associations are captured.
Merge all sources into a single canonical API representation.
- One canonical symbol record per logical API symbol
- Multiple source evidence entries per symbol
- Preserve ambiguity instead of guessing
- Track provenance for every field
At minimum each symbol record should support:
{
"id": "adsk.core.Application.get",
"kind": "method",
"name": "get",
"owner": "adsk.core.Application",
"namespace": "adsk.core",
"display_name": "Application.get",
"python_path": "adsk.core.Application.get",
"cpp_qualified_name": "adsk::core::Application::get",
"source_paths": [
"Fusion_API_Python_Reference/defs/...",
"Fusion_API_CPP_Reference/include/...",
"Fusion_API_Documentation/files/Application_get.htm"
],
"signatures": [
{
"language": "python",
"params": [],
"returns": "Application",
"static": true
}
],
"doc": {
"title": "Application.get Method",
"description": "Access to the root Application object.",
"parameters": [],
"return_description": "Return the root Application object or null if it failed.",
"samples": [],
"introduced_in": "August 2014"
},
"traits": {
"collection_like": false,
"static_constructor": true,
"compact_candidate": true
},
"provenance": {
"signature_source": "python_defs",
"doc_source": "html"
}
}- Use Python defs as canonical Python signature source where available.
- Use C++ to verify types and fill gaps.
- Use docs to enrich descriptions and versions.
- If sources disagree:
- preserve both values in provenance
- choose one canonical value using precedence
- emit a warning entry in
build/reports/merge_conflicts.md
Compute these during IR building:
collection_like- if object has
countanditem
- if object has
has_addhas_create_inputhas_add_simplesupports_samplesis_enumis_input_objectreturns_base_productis_static_constructoris_cast_helper
Write:
build/ir/symbols.jsonbuild/ir/enums.jsonbuild/ir/families.jsonbuild/reports/merge_conflicts.md
- IR contains stable IDs and provenance.
- Re-running build yields identical output ordering.
- Conflict report is deterministic.
Define the small handwritten policy layer that drives ergonomic generation.
Implement these files:
Maps compact public names to symbols or wrapper methods.
Example:
exports:
new_design: adsk.core.Documents.add:FusionDesignDocumentType
app: runtime.app
ctx: runtime.ctx
p: runtime.geom.point
vec: runtime.geom.vector
oc: runtime.geom.object_collectionMaps readable compact enum aliases.
Example:
FeatureOperations:
new_body: NewBodyFeatureOperation
new_component: NewComponentFeatureOperation
join: JoinFeatureOperation
cut: CutFeatureOperation
intersect: IntersectFeatureOperationDefines builder families and high-value compact methods.
Example:
families:
ExtrudeFeatures:
compact_method: extrude
simple_method: addSimple
builder_input: createInput
builder_terminal: addSymbols or pages to skip from compact generation.
Controls what the package exports publicly in fusion_sparse.__init__.
- Generator can consume rule files and fail clearly on invalid entries.
- Manual rule layer remains small and focused.
- No generated logic is hardcoded in handwritten runtime if it belongs in rules.
Generate the minimal but complete metadata needed by the runtime and by update tooling.
build/generated/symbol_index.pysrc/fusion_sparse/generated/enum_index.pysrc/fusion_sparse/generated/wrapper_dispatch.pybuild/generated/families.pysrc/fusion_sparse/generated/release_info.py
- compact searchable mapping of symbol IDs to metadata
- enough to support debugging, introspection, and future doc tooling
- canonical enum aliases
- reverse lookup from compact alias to Autodesk enum member
- map
objectTypestrings or class names to compact wrapper classes
- collection and builder family metadata
- corpus lock details
- generated timestamp
- corpus commit or version metadata if known
- Generated files are importable in a normal Python environment without
adsk. - Runtime can use them lazily when
adskexists.
Implement the handwritten runtime that everything else builds on.
Define a small error hierarchy:
FusionSparseErrorInvalidContextErrorUnitCoercionErrorUnsupportedOperationErrorGenerationMismatchError
This is one of the most important files.
Responsibilities:
unwrap(value):- compact wrapper to raw Autodesk object
- recursive for tuples/lists/dicts where appropriate
wrap(value):- raw Autodesk object to wrapper
- recursive for tuples
- leave primitives untouched
- do not automatically convert Autodesk vector returns into Python lists globally
wrap_callable(raw_callable):- returns a small proxy that unwraps inputs and wraps outputs
- used for delegated raw method access
Define a base wrapper:
class Ref:
raw: object
@property
def object_type(self) -> str: ...
@property
def class_type(self) -> str: ...
@property
def is_valid(self) -> bool: ...Behavior rules:
.rawis always available- raw camelCase members can be delegated through
__getattr__ - compact methods use snake_case names so they do not collide with raw camelCase names
- wrapper equality should delegate to Autodesk object equality semantics where possible
Centralize application and design resolution.
Required helpers:
app()ui()active_product()active_design(strict=True)ctx()returning an object with:.app.ui.product.design.doc.root
Also add:
new_design()new_or_active_design()
Important rule:
new_design()must document or guard against usage during command transactions becauseDocuments.addis not allowed inside command-related events.
Implement the unit-safe value system.
Required public helpers:
v(value)generic coercionu.mm(x)u.cm(x)u.m(x)u.inch(x)oru.in_(x)if naming conflictu.deg(x)u.rad(x)u.expr(text)
Rules:
- number ->
ValueInput.createByReal - string ->
ValueInput.createByString - already a
ValueInput-> pass through - wrapper around
ValueInput-> unwrap - explicit unit helpers build strings or internal-unit values consistently
Implement transient geometry helpers:
p(x, y, z=0)vec(x, y, z=0)mat_identity()oc(*items)forObjectCollection.create()plus population
Point coercion rules:
(x, y)->Point3D.create(x, y, 0)(x, y, z)->Point3D.create(x, y, z)- already point object -> pass through
Expose compact enum alias namespaces:
op.new_bodyop.new_componentop.joinop.cutop.intersectdir.positivedir.negativedir.symmetric
Keep feature detection inside the thin runtime instead of introducing a separate compatibility module.
Rules:
- prefer capability checks over explicit version checks
- use
hasattragainst raw objects when possible - keep feature-specific checks close to the compact helper or runtime context that needs them
- Runtime imports cleanly inside Fusion.
- Wrapper adaptation works for raw Autodesk objects and tuples.
- Public helpers work for basic context and value coercion.
Implement a high-value compact layer for the core modeling workflow.
Use handwritten wrapper classes backed by generated dispatch tables.
Provide top-level exported helpers:
app()ctx()new_design()
Implement DesignRef.
Required properties and methods:
.root.paramsoptional if easy.modeoptional compatibility helper if design intent fields exist.component(name=None)optional future helper
Implement ComponentRef.
Required methods for v0:
sketch(plane)extrude(profile, distance=None, op="new_body")occurrences()optionalnew_occurrence(transform=None)optional if easy
Plane resolution rules:
"xy"->xYConstructionPlane"xz"->xZConstructionPlane"yz"->yZConstructionPlane- raw plane object -> use directly
Implement SketchRef.
Required methods for v0:
line(a, b)circle(center, r)rect(a, b)point(x, y, z=0)optionalprofile(i=0)profiles()
Implementation detail:
circle((0, 0), r="20 mm")should coerce center viapand radius via value rules if needed- sketch primitives should return wrapped sketch entities where possible
Implement both compact simple path and builder path.
If distance is provided, use ExtrudeFeatures.addSimple.
Example:
root.extrude(sk.profile(), "10 mm", op="new_body")If distance is omitted or advanced options are chained, return ExtrudeBuilder.
Required builder methods for v0:
one_side(distance, direction="positive")symmetric(distance)solid(flag=True)surface()taper(angle)build()
Optional builder methods if straightforward:
participant_bodies(*bodies)from_entity(entity, offset=None)to_entity(entity, offset=None, chained=None)
- simple path ->
ExtrudeFeatures.addSimple - builder path ->
ExtrudeFeatures.createInputthenExtrudeFeatures.add
- The compact API can create a new design, sketch a circle, and extrude it.
- The simple path uses
addSimple. - The builder path uses
createInputandadd. - Raw access is preserved.
Avoid generating thousands of handwritten wrapper methods while preserving broad compatibility.
Use generated dispatch tables to wrap only known Autodesk objects into the right compact wrapper class.
Recommended wrapper strategy:
-
wrap(raw_obj)inspectsobjectTypeor Python type and returns:DesignRefComponentRefSketchRef- generic
Ref - etc.
-
Ref.__getattr__delegates unknown attributes:- if attribute is a raw Autodesk object, wrap it
- if attribute is callable, return a callable proxy that unwraps inputs and wraps outputs
- else return attribute unchanged
- Do not let dynamic passthrough hide compact method errors
- Prefer compact snake_case names so raw camelCase members remain accessible
- If passthrough becomes fragile in some edge cases, keep
.rawas the official escape hatch
- Unknown raw members are still reachable on wrappers
- Returned Autodesk objects are wrapped automatically in common cases
- Returned tuples preserve wrapping of contained Autodesk objects
Make the library itself agent-friendly.
Generate:
docs/compact_reference.mddocs/raw_mapping.mddocs/update_workflow.mdbuild/reports/symbol_stats.md
The compact reference should include, for each public compact helper:
- public compact name
- raw Autodesk mapping
- arguments
- common examples
- escape hatch notes
This is important because coding agents will search this project and should be able to map compact helpers back to the official API quickly.
- Documentation is generated from metadata plus manual templates
- Public compact methods clearly state their raw mapping
These must run in a normal Python environment.
Cover:
- corpus loading
- parser extraction
- IR merge behavior
- rule application
- code generation determinism
- adapter unwrap/wrap with mocked Autodesk-like objects
- enum alias resolution
- point and unit coercion helpers with mocked
adskfactory functions where possible
Store golden snapshots for:
- a few parsed symbol records
- generated enum alias files
- generated wrapper dispatch
- generated docs
Golden tests should fail on unintentional generator drift.
Create smoke scripts under tests/integration/fusion_scripts/:
-
smoke_context.py- resolve app, design, root
-
smoke_new_design.py- create a design document
-
smoke_sketch_extrude.py- sketch a circle and extrude
-
smoke_builder_extrude.py- use the builder path
-
smoke_raw_escape_hatch.py- call raw Autodesk API through wrapper
.raw
- call raw Autodesk API through wrapper
Create fusion/addins/FusionSparseWorkbench/ based on the Python add-in template structure:
- top-level
.py,.manifest,config.py commands/lib/or packaged library copy
Use it to validate command integration later, but do not block core progress on it.
Assume some integration steps may require Fusion to be opened and a script or add-in to be run manually unless a local MCP or automation harness exists.
Quantify value for coding agents.
- Add baseline scripts modeled after official call chains.
- Add compact scripts with equivalent behavior.
- Implement
tools/measure_sparsity.pyto compute:- characters
- lines
- tokens
adsk.symbol count
- Generate
build/reports/sparsity_report.md
- new design document
- circle sketch
- rectangle sketch
- simple extrude
- builder extrude
- Report is generated automatically
- Compact layer clearly beats the baseline on the target metrics
Keep the project maintainable as Fusion changes.
- Snapshot previous IR under
build/ir/snapshots/orsnapshots/. - Implement
tools/diff_ir.py. - Produce reports:
- added symbols
- removed symbols
- changed signatures
- changed enums
- new doc pages
- release-risk summary
- Detect high-risk topics:
- design intent changes
- new design modes
- new external component APIs
- embedded Python version changes
On corpus update:
- refresh corpus checkout
- rebuild IR
- run diff report
- inspect merge conflicts
- update rule overrides only if needed
- regenerate code
- run unit tests
- run at least one Fusion smoke script
- inspect benchmark drift
- Update is mostly mechanical
- Diff report is readable and deterministic
Allow local automation if the environment already supports it.
This is optional and should not block the core library.
Use linked script/add-in folders and manual execution in Fusion.
If a local Fusion MCP setup already exists, use it for:
- executing smoke scripts
- capturing screenshots
- verifying outcomes
- keeping Fusion API calls on the main thread via custom-event-based task routing
Do not make MCP a required dependency of the core library.
Never call Fusion API from background threads directly. If background execution is needed in an add-in or MCP harness, marshal work to the main thread using Fusion's event system.
These rules are mandatory.
Examples:
new_designone_sideparticipant_bodies
Reason:
- avoids collisions with raw Autodesk camelCase members
- is Pythonic
- makes it obvious what belongs to the compact layer
Examples:
component.raw.features.extrudeFeaturescomponent.featuresextrude_input.setDistanceExtent(...)
If passthrough is enabled, raw camelCase members should still be callable directly on wrappers.
Never remove this.
Examples:
5means 5 cm when used as a length0.5means 0.5 rad when used as an angle
Examples:
"10 mm""90 deg""d0 / 2"
Examples:
Good:
root = design.root
sk = root.sketch("xy")Bad:
sk = sketch("xy")unless a context object is explicitly being used and makes the target obvious.
Examples:
extrude(..., "10 mm")for simple useextrude(...).one_side(...).build()for advanced use
Everything should accept either:
- compact wrapper objects
- raw Autodesk objects
- simple coercible literals such as tuples or expressions
This is the public surface to implement first.
import fusion_sparse as fx
fx.app()
fx.ctx()
fx.new_design()
fx.p(x, y, z=0)
fx.vec(x, y, z=0)
fx.oc(*items)
fx.u.mm(x)
fx.u.cm(x)
fx.u.deg(x)
fx.u.rad(x)
fx.u.expr(text)
design.root
component.sketch("xy" | "xz" | "yz" | raw_plane)
component.extrude(profile, distance=None, op="new_body")
sketch.line(a, b)
sketch.circle(center, r)
sketch.rect(a, b)
sketch.profile(i=0)
sketch.profiles()
builder.one_side(distance, direction="positive")
builder.symmetric(distance)
builder.solid(flag=True)
builder.surface()
builder.taper(angle)
builder.build()Do not expand this public surface until the generator and runtime are stable.
Implement in this order.
Create repo skeleton, pyproject.toml, CLI scaffolding, placeholder rules.
Implement corpus loader and lockfile.
Implement Python defs parser with tests.
Implement C++ enum and signature verifier parser.
Implement doc parser and symbol-link normalization.
Implement IR merge pipeline and write stable JSON outputs.
Implement rule loader and override application.
Generate metadata artifacts only. Do not generate runtime code yet.
Implement handwritten runtime core:
- errors
- adapter
- refs
- values
- geom
- context
- enums
Implement compact wrappers:
- DesignRef
- ComponentRef
- SketchRef
- ExtrudeBuilder
Hook wrapper dispatch to generated metadata.
Create smoke scripts and run them in Fusion.
Implement sparsity benchmarks and report.
Implement release diff tooling.
Only after all of the above, add optional add-in harness and optional MCP integration.
The first execution phase is done when all of the following are true:
- The project can ingest a local
FusionAPIReferencecheckout and produce a merged IR. - The project can generate deterministic metadata artifacts.
- The runtime library imports inside Fusion.
fx.new_design()works.root.sketch("xy")works.sk.circle((0, 0), r="20 mm")works.root.extrude(sk.profile(), "10 mm", op="new_body")works.- The builder path works for at least one one-side extent case.
.rawaccess works.- Unit tests pass.
- At least three Fusion smoke scripts run successfully.
- A sparsity report is generated and shows clear code reduction for common workflows.
- An update diff report can be generated from two IR snapshots.
Mitigation:
- treat them as primary but not exclusive
- verify against headers and docs
- preserve ambiguity in IR
Mitigation:
- keep header parsing narrow and high-value
- use it mainly for enums and verification
- never block the build on perfect C++ parsing
Mitigation:
- keep compact methods explicit
- keep
.rawofficial and well-documented - if needed, reduce passthrough scope and require
.rawfor edge cases
Mitigation:
- keep runtime stdlib-only
- avoid heavy modern features in runtime code
- ship
.pyonly
Mitigation:
- document and guard
- keep document creation outside command execute contexts
- add integration coverage for script vs add-in scenarios
Mitigation:
- compatibility layer should use feature detection
- smoke tests should include explicit checks if local Fusion version supports design intent
Mitigation:
- enforce the first-cut public API
- do not expand beyond sketch plus extrude until generator and tests are solid
Implement the work in small, reviewable slices.
For every slice:
- modify the smallest number of files possible
- add or update tests immediately
- regenerate outputs if generator behavior changed
- never manually patch generated files
- document any ambiguity in a report instead of guessing
- preserve deterministic ordering in all generated artifacts
- keep runtime code dependency-free
- prefer simpler designs that preserve raw compatibility over elaborate abstractions
When uncertain about an API symbol:
- inspect Python defs
- inspect C++ headers
- inspect docs
- if still ambiguous, mark the IR field as uncertain and continue
Do not stall the project on perfect completeness.
The first concrete implementation session should do exactly this:
- scaffold repo and CLI
- add corpus loader
- parse Python defs
- build initial IR for a tiny allowlist:
ApplicationDocumentsDocumentTypesValueInputDesignComponentSketchExtrudeFeatures
- generate a minimal symbol index
- implement
new_design,p,u,ComponentRef.sketch,SketchRef.circle, andComponentRef.extrude - create and run the first smoke script in Fusion
That thin slice proves the full architecture end-to-end. Only after it works should the implementation widen to the rest of the API surface.
These are the core external references this plan assumes are available locally or online:
- AutodeskFusion360/FusionAPIReference
- AutodeskFusion360/FusionMCPSample
- Fusion API User's Manual
- Fusion API Reference Manual
- Python Specific Issues
- Python Add-in Template
- Creating Scripts and Add-Ins
- Commands
- Working in a Separate Thread
- Understanding Units in Fusion
- Documents, Products, Components, Occurrences, and Proxies
- What's New in the Fusion API
The project should encode the useful parts of those references into generated metadata and handwritten runtime rules so that future development depends less on re-reading the raw sources.