main
md 273 lines 13.5 KB
Rendered Raw
1 ---
2 name: compiler-orchestrator
3 description: Orchestrate the Rust compiler port end-to-end. Discovers the current frontier, fixes failing passes, ports new passes, reviews, and commits in a loop.
4 ---
5
6 # Compiler Orchestrator
7
8 Automatically drive the Rust compiler port forward by discovering the current state, fixing failures, porting new passes, reviewing, and committing — in a continuous loop.
9
10 Arguments:
11 - $ARGUMENTS: Optional. A pass name to start from, or `status` to just report current state without acting.
12
13 ## Pass Order Reference
14
15 These are the passes in Pipeline.ts order, with their exact log names:
16
17 | # | Log Name | Kind | Notes |
18 |---|----------|------|-------|
19 | 1 | HIR | hir | |
20 | 2 | PruneMaybeThrows | hir | Validation: validateContextVariableLValues, validateUseMemo after |
21 | 3 | DropManualMemoization | hir | Conditional |
22 | 4 | InlineImmediatelyInvokedFunctionExpressions | hir | |
23 | 5 | MergeConsecutiveBlocks | hir | |
24 | 6 | SSA | hir | |
25 | 7 | EliminateRedundantPhi | hir | |
26 | 8 | ConstantPropagation | hir | |
27 | 9 | InferTypes | hir | Validation: validateHooksUsage, validateNoCapitalizedCalls after (conditional) |
28 | 10 | OptimizePropsMethodCalls | hir | |
29 | 11 | AnalyseFunctions | hir | |
30 | 12 | InferMutationAliasingEffects | hir | |
31 | 13 | OptimizeForSSR | hir | Conditional: outputMode === 'ssr' |
32 | 14 | DeadCodeElimination | hir | |
33 | 15 | PruneMaybeThrows (2nd) | hir | Reuses existing fn, just needs 2nd call + log in pipeline.rs |
34 | 16 | InferMutationAliasingRanges | hir | Validation block (8 validators) after (conditional) |
35 | 17 | InferReactivePlaces | hir | Validation: validateExhaustiveDependencies after (conditional) |
36 | 18 | RewriteInstructionKindsBasedOnReassignment | hir | Validation: validateStaticComponents after (conditional) |
37 | 19 | InferReactiveScopeVariables | hir | Conditional: enableMemoization |
38 | 20 | MemoizeFbtAndMacroOperandsInSameScope | hir | |
39 | -- | outlineJSX | hir | Between #20 and #21, conditional: enableJsxOutlining, no log entry |
40 | 21 | NameAnonymousFunctions | hir | Conditional |
41 | 22 | OutlineFunctions | hir | Conditional |
42 | 23 | AlignMethodCallScopes | hir | |
43 | 24 | AlignObjectMethodScopes | hir | |
44 | 25 | PruneUnusedLabelsHIR | hir | |
45 | 26 | AlignReactiveScopesToBlockScopesHIR | hir | |
46 | 27 | MergeOverlappingReactiveScopesHIR | hir | |
47 | 28 | BuildReactiveScopeTerminalsHIR | hir | |
48 | 29 | FlattenReactiveLoopsHIR | hir | |
49 | 30 | FlattenScopesWithHooksOrUseHIR | hir | |
50 | 31 | PropagateScopeDependenciesHIR | hir | |
51 | 32 | BuildReactiveFunction | reactive | |
52 | 33 | AssertWellFormedBreakTargets | debug | Validation |
53 | 34 | PruneUnusedLabels | reactive | |
54 | 35 | AssertScopeInstructionsWithinScopes | debug | Validation |
55 | 36 | PruneNonEscapingScopes | reactive | |
56 | 37 | PruneNonReactiveDependencies | reactive | |
57 | 38 | PruneUnusedScopes | reactive | |
58 | 39 | MergeReactiveScopesThatInvalidateTogether | reactive | |
59 | 40 | PruneAlwaysInvalidatingScopes | reactive | |
60 | 41 | PropagateEarlyReturns | reactive | |
61 | 42 | PruneUnusedLValues | reactive | |
62 | 43 | PromoteUsedTemporaries | reactive | |
63 | 44 | ExtractScopeDeclarationsFromDestructuring | reactive | |
64 | 45 | StabilizeBlockIds | reactive | |
65 | 46 | RenameVariables | reactive | |
66 | 47 | PruneHoistedContexts | reactive | |
67 | 48 | ValidatePreservedManualMemoization | debug | Conditional |
68 | 49 | Codegen | ast | |
69
70 Validation passes (no log entries, tested via CompileError/CompileSkip events):
71 - After PruneMaybeThrows (#2): validateContextVariableLValues, validateUseMemo
72 - After InferTypes (#9): validateHooksUsage, validateNoCapitalizedCalls (conditional)
73 - After InferMutationAliasingRanges (#16): 8 validators (conditional)
74 - After InferReactivePlaces (#17): validateExhaustiveDependencies (conditional)
75 - After RewriteInstructionKindsBasedOnReassignment (#18): validateStaticComponents (conditional)
76 - After PruneHoistedContexts (#45): validatePreservedManualMemoization (conditional)
77 - After Codegen (#46): validateSourceLocations (conditional)
78
79 ## Orchestrator Log
80
81 Maintain a log file at `compiler/docs/rust-port/rust-port-orchestrator-log.md` that tracks all progress.
82
83 ### Log file format
84
85 ```markdown
86 # Status
87
88 HIR: complete (1717/1717)
89 PruneMaybeThrows: complete (1717/1717)
90 DropManualMemoization: complete (1717/1717)
91 ...
92 AnalyseFunctions: partial (1700/1717)
93 InferMutationAliasingEffects: todo
94 ...
95
96 # Logs
97
98 ## 20260318-143022 Port AnalyseFunctions pass
99
100 Ported AnalyseFunctions from TypeScript to Rust. Added new crate react_compiler_analyse_functions.
101 1700/1717 tests passing, 17 failures in edge cases with nested functions.
102
103 ## 20260318-141500 Fix SSA phi node ordering
104
105 Fixed phi node operand ordering in SSA pass that caused 3 test failures.
106 All 1717 tests now passing through OptimizePropsMethodCalls.
107 ```
108
109 ### Status section
110
111 The `# Status` section lists every pass from #1 to #49 with one of:
112 - `complete (N/N)` — all tests passing through this pass
113 - `partial (passed/total)` — some test failures remain
114 - `todo` — not yet ported
115
116 Update the Status section after every test run to reflect the latest results.
117
118 ### Log entries
119
120 Add a new log entry (below the most recent one, so newest entries are at the bottom) whenever:
121 - A pass is newly ported
122 - Test failures are fixed
123 - A commit is made
124
125 Entry format: `## YYYYMMDD-HHMMSS <short-summary>` followed by 1-3 lines describing what changed.
126
127 Use the current timestamp when creating entries. Get it via `date '+%Y%m%d-%H%M%S'`.
128
129 ### Initialization
130
131 On first run, if the log file doesn't exist, create it with the Status section populated from the current state (read pipeline.rs and run tests to determine pass statuses).
132
133 ## Core Loop
134
135 **Main context role**: The main context is ONLY an orchestration loop. It parses subagent results, updates the orchestrator log, prints status, and launches the next subagent. The main context MUST NOT read source code, investigate failures, debug issues, or make edits directly. ALL implementation work — fixing, porting, reviewing, verifying — happens in subagents.
136
137 Execute these steps in order, looping back to Step 1 after each commit:
138
139 ### Step 1: Discover Frontier
140
141 Run `test-rust-port` with `--json` to get machine-readable results:
142
143 ```bash
144 bash compiler/scripts/test-rust-port.sh --json 2>/dev/null
145 ```
146
147 This outputs a single JSON object with fields: `pass`, `autoDetected`, `total`, `passed`, `failed`, `frontier`, `perPass`, `failures`.
148
149 Parse the JSON to extract:
150 - `passed`, `failed`, `total` counts
151 - `frontier` — the earliest pass with failures, or `null` if all clean
152 - `perPass` — per-pass breakdown of passed/failed counts
153
154 If frontier is `null`, determine the next action:
155 - The `pass` field shows the last ported pass (auto-detected from pipeline.rs)
156 - Look up the next pass in the Pass Order Reference table
157 - Otherwise, the mode is **PORT** for that next pass
158
159 If frontier is a pass name, the mode is **FIX** for that pass. Use `--failures` to get the full list of failing fixture paths:
160 ```bash
161 bash compiler/scripts/test-rust-port.sh <FrontierPassName> --failures
162 ```
163
164 Then run specific failing fixtures to get diffs for investigation:
165 ```bash
166 bash compiler/scripts/test-rust-port.sh <FrontierPassName> <fixture-path> --no-color
167 ```
168
169 Also check if `compiler/docs/rust-port/rust-port-orchestrator-log.md` exists. If not, create it with the Status section populated from the current state.
170
171 Update the orchestrator log Status section, then proceed to Step 2.
172
173 ### Step 2: Report Status
174
175 Print a status report:
176 ```
177 ## Orchestrator Status
178 - Ported passes: <count> / 49
179 - Test results: <passed> passed, <failed> failed (<total> total)
180 - Frontier: #<num> <PassName> (<FIX|PORT> mode) — or "none (all clean)"
181 - Action: <what will happen next>
182 ```
183
184 If `$ARGUMENTS` is `status`, stop here.
185
186 ### Step 3: Act on Frontier
187
188 **Do NOT investigate, read source code, or debug in the main context.** Always delegate to a subagent.
189
190 #### 3a. FIX mode (frontier is a ported pass with failures)
191
192 Launch two subagents **in parallel** to diagnose the failures:
193
194 1. **Review subagent**: Run `/compiler-review` on the failing pass to identify obvious issues — missing features, incorrect porting of logic, divergences from the TypeScript source.
195
196 2. **Analysis subagent**: A `general-purpose` subagent that investigates the actual test failures. Its prompt MUST include:
197 - **The pass name** and its position number
198 - **The full test failure output** (copy it verbatim)
199 - **Instructions**: Run failing fixtures individually with `bash compiler/scripts/test-rust-port.sh <PassName> <fixture-path> --no-color` to get diffs. Analyze the diffs to determine what the Rust port is doing wrong. Read the corresponding TypeScript source to understand expected behavior. Report findings but do NOT make fixes yet.
200 - **Architecture guide path**: `compiler/docs/rust-port/rust-port-architecture.md`
201 - **Pipeline path**: `compiler/crates/react_compiler/src/entrypoint/pipeline.rs`
202
203 After both subagents complete, **synthesize their results** to determine a plan of action. The review may surface porting gaps that explain the test failures, and the failure analysis may reveal issues the review missed. Use both inputs to form a complete picture.
204
205 Then launch a single `general-purpose` subagent to fix the failures. The subagent prompt MUST include:
206
207 1. **The pass name** and its position number
208 2. **The synthesized diagnosis** — both the review findings and the failure analysis
209 3. **Instructions**: Fix the test failures in the Rust port. Do NOT re-port from scratch. Use the diagnosis to guide fixes. After fixing, run `bash compiler/scripts/test-rust-port.sh <PassName>` to verify. Repeat until 0 failures or you've made 3 fix attempts without progress.
210 4. **Architecture guide path**: `compiler/docs/rust-port/rust-port-architecture.md`
211 5. **Pipeline path**: `compiler/crates/react_compiler/src/entrypoint/pipeline.rs`
212
213 After the fix subagent completes:
214 1. Re-run `bash compiler/scripts/test-rust-port.sh --json 2>/dev/null` to get updated counts and frontier
215 2. If still failing, repeat the parallel diagnosis + fix cycle (max 3 rounds total)
216 3. Once clean (or after 3 rounds), update the orchestrator log Status section and add a log entry
217 4. Go to Step 4 (Review and Commit)
218
219 #### 3b. PORT mode (frontier is the next unported pass)
220
221 Handle special cases first:
222 - **Second PruneMaybeThrows call (#15)**: Launch a `general-purpose` subagent to add a second call to `prune_maybe_throws` + `log_debug!` in pipeline.rs, then run tests.
223 - **outlineJSX (between #20 and #21)**: Conditional on `enableJsxOutlining`. Has no log entry. Launch a subagent to handle inline or via the compiler-port pattern.
224 - **Conditional passes** (#3, #13, #19, #21, #22): Note the condition when delegating.
225
226 For standard passes, launch a single `general-purpose` subagent with these instructions:
227
228 1. **Pass name**: `<PassName>` (position #N in the pipeline)
229 2. **Instructions**: Port the `<PassName>` pass from TypeScript to Rust. Follow these steps:
230 a. Read the architecture guide at `compiler/docs/rust-port/rust-port-architecture.md`
231 b. Read the pass documentation in `compiler/packages/babel-plugin-react-compiler/docs/passes/`
232 c. Find the TypeScript source by following the import in `compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts`
233 d. Read the Rust pipeline at `compiler/crates/react_compiler/src/entrypoint/pipeline.rs` and existing crate structure
234 e. Port the pass, create/update crates as needed, wire into pipeline.rs
235 f. Run `bash compiler/scripts/test-rust-port.sh <PassName>` and fix failures in a loop until 0 failures (max 5 attempts)
236 g. Report: files created/modified, final test count, any remaining issues
237 3. **Special notes** (if any — e.g., conditional gating, reuse of existing functions)
238
239 After the subagent completes:
240 1. Re-run `bash compiler/scripts/test-rust-port.sh --json 2>/dev/null` to get updated counts and frontier
241 2. Update the orchestrator log Status section and add a log entry
242 3. Go to Step 4 (Review and Commit)
243
244 ### Step 4: Review and Commit
245
246 Use `/compiler-commit <title>` to review, verify, and commit the changes. This skill:
247 1. Runs `/compiler-verify` (tests, lint, format)
248 2. Runs `/compiler-review` on uncommitted changes — stops if issues are found
249 3. Updates the orchestrator log with test results
250 4. Commits with the correct `[rust-compiler]` prefix
251
252 Choose a descriptive commit title based on what the subagent did (e.g., "Port AnalyseFunctions pass" or "Fix SSA phi node ordering").
253
254 After committing:
255 1. Parse the commit hash from the output
256 2. Add a log entry noting the commit
257 3. Work continues — commits are checkpoints, not stopping points
258
259 ### Step 5: Loop
260
261 Go back to Step 1. The loop continues until:
262 - All passes are ported and clean (up to #49)
263 - An unrecoverable error occurs
264
265 ## Key Principles
266
267 1. **Earliest failure wins**: Even a single test failure in pass #2 must be fixed before working on pass #11. Early errors cascade — a bug in lowering can cause false failures in every downstream pass.
268
269 2. **Cumulative testing**: `test-rust-port.sh <PassName>` tests ALL passes up to and including the named pass. A clean result for the last pass implies all earlier passes are clean too.
270
271 3. **Incremental commits**: Commit after each meaningful unit of progress. Don't batch multiple passes into one commit. Each commit should leave the tree in a clean state.
272
273 4. **Delegate everything**: The main context MUST NOT read source code, investigate bugs, or make edits. It only: parses subagent results, updates the orchestrator log, prints status, and launches the next subagent. All code reading, debugging, fixing, porting, reviewing, and committing happens in subagents.