Deep source: docs/architecture/Execution/README.md and sub-pages (code-execution.md, execution-guard.md, pytest-bridge.md, mcp-dispatch.md).
- Orchestrator:
source/DevTools.Execution/Services/ExecutionOrchestrator.cs. - DI:
source/DevTools.Execution/ExecutionExtensions.cs. - Providers discover roots and nodes. Strategies execute selected nodes.
AssemblyExecutionProviderhandles.dll.ScriptExecutionProviderhandles directories with*script.py,*script.fsx, and*script.csx.ContainerMode(Script,Assembly) describes how code is organised;ExecutionMode(Python,IronPython,FSharp,CSharp,Dotnet,Unsupported) describes the execution backend.
Shared execution does not own host APIs. It calls abstractions defined in source/DevTools.Execution.Abstractions/:
IHostContextExecutor— run code on host main threadICommandDiscovery— discover executable nodesICommandRunner— invoke a discovered commandIDocumentBridge— open/close documents (Revit/AutoCAD)ICompiledScriptBridge— compiled script cachingExecutionGuardMode— enum:Passthrough,SuppressExecutionGuardContext— ambientAsyncLocalpropagating mode + feedback summary
Additional interfaces in source/DevTools.Execution/Interfaces/:
IPythonBridge— Python.NET runtimeIIronPythonBridge— IronPython runtimeIDebuggerBridge(inDevTools.Presentation.Interfaces) — attach/detach debugger
Host projects register implementations via AddExecutionServices():
- Revit:
source/RevitDevTool/Hosting/RevitHostingExtensions.cs - AutoCAD:
source/AcadDevTool/Hosting/AcadHostingExtensions.cs
The AddExecutionServices() call is the central DI hub — it registers orchestrator, MCP in-host pipe server (DevToolsPipeServer), pytest handler, and all strategy factories.
Revit-specific guard that auto-dismisses dialogs and auto-resolves/rollbacks transaction failures during AI-driven execution. Architecture:
Caller sets ExecutionGuardContext.Mode → RevitHostContextExecutor reads mode
→ ExecutionGuard.Begin(mode)
→ DialogSuppressionScope (UIApplication.DialogBoxShowing)
→ FailureSuppressionScope (Application.FailuresProcessing)
→ Only rollback info published to ExecutionGuardContext.RollbackSummary
→ Warnings/dialogs suppressed silently (logged at Debug level)
| File | Role |
|---|---|
source/DevTools.Execution.Abstractions/ExecutionGuardMode.cs |
Mode enum: Passthrough, Suppress |
source/DevTools.Execution.Abstractions/ExecutionGuardContext.cs |
AsyncLocal: mode + rollback summary |
source/RevitDevTool.Core/Execution/IExecutionGuard.cs |
Guard factory interface (no logging deps) |
source/RevitDevTool.Core/Execution/ExecutionGuard.cs |
Factory combining scopes |
source/RevitDevTool.Core/Execution/DialogSuppressionScope.cs |
DialogBoxShowing handler |
source/RevitDevTool.Core/Execution/FailureSuppressionScope.cs |
FailuresProcessing handler |
source/RevitDevTool.Core/Execution/ExecutionGuardFeedback.cs |
Internal tracking (not public) |
| Caller | Mode | Rationale |
|---|---|---|
| MCP tool/prompt/resource | Suppress |
AI cannot interact with UI |
| Pytest session | Suppress |
Tests must be deterministic |
| UI command tree / debugger | Passthrough |
User may want dialogs |
Only unresolvable failure rollbacks are surfaced to AI callers via ExecutionGuardContext.RollbackSummary. All other suppressions (warnings dismissed, errors auto-resolved, dialogs auto-dismissed) are silent — the operation succeeded and AI doesn't need to know. Warnings remain queryable via Document.GetWarnings() if the agent needs quality checks.
- RevitDevTool.Core has no logging dependency: guard is pure Revit API; logging lives in host executor.
- Reference-counted scopes: nested MCP calls share one event subscription; safe for FIFO queue.
- AsyncLocal propagation: avoids changing
IHostContextExecutorinterface; each async flow isolated. - Only rollback feedback: AI only needs to know when operations fail, not when warnings are dismissed.
- net48 compatible: uses
Polyfillpackage forLocktype; no .NET 9+ APIs. - PickObject not affected: modal selection is not a
DialogBoxShowingevent. - Save prompts → No:
TaskDialog_Save_Fileoverrides withTaskDialogResult.No.
- Python: PEP 723 dependencies through
Parser.py, Pixi preferred, pip/pyRevit fallback. Startup runspixi --versionafter install check; non-zero exit → pip backend. - IronPython: Python files ending
_ipy_script.py. - F#:
.fsx, NuGet resolution under%APPDATA%\RevitDevTool\nuget, 30 second compile timeout. - C#:
.csx, Roslyn compilation cache, 30 second compile timeout.
- Confirm whether the change is provider, strategy, orchestrator, node model, file watcher, package service, or host adapter.
- Keep host-thread rules in host adapters.
- If changing execution guard: verify both
SuppressandPassthroughpaths work; test reference counting with nested calls. - Run the narrowest host build and related unit tests from
verification.md. - Remember current tests are shallow; add focused tests for shared pure logic when behavior changes.