The Orchestrator¶
The Orchestrator operates as the primary deterministic state machine for Protostar. It is responsible for bridging the gap between declarative module configurations and imperative disk/shell mutations, ensuring the local filesystem is manipulated safely and predictably.
To guarantee idempotency and prevent partial initialization states (e.g., half-written configuration files following a pre-flight failure), the Orchestrator enforces a strict, multi-phase execution topology.
-
Idempotent Execution
Execution logic is strictly decoupled from state definition. Running the Orchestrator repeatedly yields the same mathematical environment baseline without corrupting existing user configurations.
-
Deterministic Sequencing
Dependencies and tasks are not executed arbitrarily. The Orchestrator enforces a strict, statically defined execution sequence, ensuring that structural scaffolding and abstract syntax trees (like TOML payloads) are fully resolved and merged before any shell subprocesses attempt to read them.
-
Telemetry & Triage
Acts as the top-level exception handler. Traps
sys.exit, OS-level I/O constraints, and unhandled runtime exceptions to provide clean terminal exits or automated GitHub crash reports.
Execution Topology¶
The Orchestrator processes the environment payload in a distinct lifecycle. State aggregation is strictly isolated from the side-effect phase, ensuring that execution only proceeds if the host system satisfies all required boundary conditions.
flowchart TD
%% Styling
classDef core fill:#1e293b,stroke:#00e5ff,stroke-width:2px,color:#fff;
classDef phase fill:#334155,stroke:#475569,stroke-width:1px,color:#e2e8f0;
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#fff;
classDef success fill:#14532d,stroke:#4ade80,stroke-width:1px,color:#fff;
%% Nodes
CLI([CLI Invocation]) --> O[Orchestrator]:::core
subgraph VerificationPhase [Verification Phase]
direction TB
C{Collision Intercept}:::phase
C -- Conflicting Configs --> P[TUI: Merge / Overwrite / Abort]
P -- Abort --> Exit1([Safe Exit Code 1]):::error
C -- Clean Workspace --> F[Pre-Flight Checks]:::phase
P -- Authorize --> F
F -- Missing Binaries --> Exit2([Safe Exit Code 1]):::error
end
O --> VerificationPhase
subgraph AggregationPhase [Aggregation Phase]
direction LR
M[Manifest Aggregation]:::phase
L[Language Modules] -.-> E[(EnvironmentManifest)]
T[Tooling Modules] -.-> E
P_Pre[Domain Presets] -.-> E
M --> L & T & P_Pre
end
VerificationPhase -- System Nominal --> AggregationPhase
subgraph SideEffectRealization [Side-Effect Realization]
direction TB
X[System Executor]:::core
D1[Validate & Merge ASTs]
D2[Write Directories & Files]
D3[Execute Shell Subprocesses]
X --> D1 --> D2 --> D3
end
E --> SideEffectRealization
SideEffectRealization --> End([Environment Stabilized]):::success
The Lifecycle Phases¶
Before a single byte of memory is allocated for the manifest payload, the Orchestrator scans the local directory for module-specific collision markers (e.g., an existing pyproject.toml or Cargo.toml).
-
Interactive Environments: Protostar halts and launches a TUI prompting the developer to
Merge,Overwrite, orAbort. -
Headless Environments (CI/CD): Protostar safely aborts with a non-zero exit code to prevent destructive mutations, unless the
-f / --forceflag is explicitly provided (which defaults to a safeMERGEstrategy).
Every loaded module executes its pre_flight() method. This step guarantees that all required system binaries (like uv, cargo, git, or direnv) are installed and accessible in the system $PATH. If a dependency is missing, execution halts immediately before any disk I/O occurs.
The Orchestrator iterates through the universal System Workspace, Language, Tooling, and Preset modules. Each module deterministically appends its required dependencies, ignores, and configuration payloads to the EnvironmentManifest. Global configuration injections (e.g., custom PyPI dependencies) are appended last to ensure they override module defaults.
The Orchestrator hands the fully resolved manifest to the SystemExecutor. The executor flushes the state to disk in a highly specific topological order:
- Validates existing TOML files for syntax errors.
- Creates directories and injects base files.
- Modifies configurations via AST deep-merging.
- Writes deduplicated ignore files and Docker artifacts.
- Writes local IDE settings.
- Executes sequential subprocesses (package resolution, git hooks).
Telemetry & Crash Reporting¶
The Orchestrator serves as the absolute boundary for exception propagation. By trapping errors at the highest level, it guarantees that users are never presented with a raw, unformatted Python stack trace unless explicitly requested via the --verbose flag.
- Expected Anomalies: Standard errors like
FileExistsError,OSError(e.g., read-only filesystems), orRuntimeError(e.g., network timeouts during dependency resolution) are caught and gracefully presented as a clean abort message in the terminal. - Critical Failures: If Protostar encounters an unhandled internal exception (a genuine bug or AST parsing collapse), it traps the stack trace, collects a vector of the environment state, and outputs a URL-encoded link. Clicking this link instantly opens a pre-populated GitHub issue so the telemetry isn't lost to the void.
Simulated Critical Failure Payload
When a catastrophic failure occurs, the Orchestrator encodes the following telemetry into the GitHub issue body:
Environment¶
- OS: Darwin 25.3.0
- Python: 3.14.3
- Command:
protostar init --python --astro --crash-test
Traceback¶
Traceback (most recent call last):
File "/opt/homebrew/bin/protostar", line 8, in <module>
sys.exit(main())
File "/opt/homebrew/lib/python3.12/site-packages/protostar/cli.py", line 150, in handle_init
engine.run()
File "/opt/homebrew/lib/python3.12/site-packages/protostar/orchestrator.py", line 105, in run
raise TypeError("INTENTIONAL_CRASH")
TypeError: INTENTIONAL_CRASH
API Reference¶
Core Interface: Orchestrator
protostar.orchestrator.Orchestrator ¶
Manages the lifecycle of the Python environment scaffolding process.
Source code in src/protostar/orchestrator.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |
__init__ ¶
Initializes the orchestrator with the requested modules and presets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modules
|
list[BootstrapModule]
|
The ordered stack of bootstrap layers to execute. |
required |
config
|
ProtostarConfig
|
The active Protostar configuration instance. |
required |
presets
|
list[PresetModule] | None
|
Domain-specific dependency and directory presets. Defaults to an empty list. |
None
|
docker
|
bool
|
If True, scaffolds a .dockerignore from the manifest ignores. Defaults to False. |
False
|
force
|
bool
|
If True, bypasses interactive prompts and forces a merge on collisions. Defaults to False. |
False
|
Source code in src/protostar/orchestrator.py
run ¶
Executes the pre-flight, build, and realization phases.
Source code in src/protostar/orchestrator.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |