optimize-fsharp-typecheck-graph
Skill23 starsChanged 32 days agoMITView on GitHub
Optimize an F# project's graph-based type-checking critical path with measured compiler evidence. Use when an F# build spends substantial time in type checking, a `.graph.md` file shows excessive file dependencies, shared namespaces or auto-open modules serialize checking, signature files may unblock parallel work, or a compile-performance refactor needs source- and binary-compatibility validation.
In this repository16 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- fsharp-async-compositionSkill
- fsharp-binary-compatibilitySkill
- fsharp-env-capabilitiesSkill
- fsharp-failure-pathsSkill
- fsharp-idiom-reviewSkill
- fsharp-iwsam-errorsSkill
- fsharp-library-api-designSkill
- fsharp-native-aotSkill
- fsharp-nullness-interopSkill
- fsharp-performance-typesSkill
- fsharp-serializationSkill
- fsharp-signature-filesSkill
- fsharp-verify-apiSkill
- parse-dont-validateSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
15 rules. About 0 are common, 13 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈13
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 9
Do not treat a simpler graph as proof of a faster build.
- Distinctive: line 19
Use repeated runs and compare medians.
- Distinctive: line 20
Keep the workload, flags, and cleanup procedure identical for both cases.
- Distinctive: line 48
Check the untyped source constructs that make the compiler infer a dependency:
- Distinctive: line 58
Treat the graph as a conservative superset.
- Distinctive: line 85
Keep the existing public path when the optimization does not require a public move.
- Distinctive: line 87
Add no facade or auto-open file unless the existing consumer contract requires that behavior.
- Very specific: line 89
Use assembly-level AutoOpen only when implicit source lookup must remain after a justified namespace or module change.
- Very specific: line 91
Treat assembly-level AutoOpen as one conditional compatibility tactic.
- Distinctive: line 108
Run the repository's tests.
- Distinctive: line 110
Use only the documented public imports and computation-expression values.
- Distinctive: line 112
Run an already-compiled consumer when binary compatibility is required.
- Distinctive: line 113
Check each target framework and relevant conditional-compilation branch.
- Distinctive: line 115
Do not infer compatibility from repository tests alone.
- Distinctive: line 140
Keep, revise, or revert decision
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Optimize F# Type-check Graph
Make the compiler's conservative file-dependency graph smaller and shallower. Do not treat a simpler graph as proof of a faster build. Prove measurement, dependency structure, and compatibility separately.
1. Fix the measurement contract
Record the project, SDK, compiler version, configuration, target framework, and build command. Record the machine conditions and build state. Time the compiler phase and each file activity. Also time the complete build. Define the run count, warm-up policy, and minimum useful improvement.
Use repeated runs and compare medians. Keep the raw reports. Keep the workload, flags, and cleanup procedure identical for both cases.
Complete this step when another person can reproduce the baseline. The baseline must identify the dominant compiler activities.
2. Capture the current graph
These diagnostic flags depend on the F# compiler version. Check them with the selected SDK before collecting a baseline. Confirm that the build creates both the graph and timing report. A successful build alone does not prove diagnostic support.
Extend, rather than replace, OtherFlags for the project under test:
<OtherFlags>$(OtherFlags) --test:GraphBasedChecking --test:DumpCheckingGraph --times:report.csv</OtherFlags>Build with the measurement contract. Preserve the generated .graph.md file
and timing CSV. Identify:
- the longest dependency chain
- high-fan-out files that gate many successors
- expensive
CheckOneImplFileactivities on that chain - independent files that the graph unnecessarily serializes
Complete this step when each proposed edit names its target edge or bottleneck.
3. Classify conservative edges
Check the untyped source constructs that make the compiler infer a dependency:
- Types exposed directly in a shared namespace can link later files that use that namespace.
- A global namespace can link the file to all later files.
- A non-prefixed
[<AutoOpen>]module can link the file to all later files. - A large module or file can become a genuine bottleneck for many dependents.
- Explicit
open, qualified names, inheritance, extensions, and inferred types can represent real dependencies.
Treat the graph as a conservative superset. The compiler can infer a syntactic edge that the program does not require.
4. Choose the least disruptive cut
Match one experiment to the measured cause:
- For unnecessary shared-namespace edges, isolate internal declarations when the existing API contract permits the change.
- For an expensive high-fan-out implementation, test an
.fsifile. Its smaller signature can unblock dependent files. - For a global or auto-open declaration, remove false dependencies without changing its public lookup behavior.
- For a large real boundary, test a file, module, or project split that matches the architecture.
Measure each cut before you combine cuts. Fewer edges can produce little improvement when other work dominates the build.
5. Preserve the existing public contract
Inspect current source imports, CLR names, extension lookup, reflection usage, and compiled consumers. Preserve the required behavior with the smallest repository-specific mechanism.
Apply these rules:
- Keep the existing public path when the optimization does not require a public move.
- Add no facade or auto-open file unless the existing consumer contract requires that behavior.
- Use assembly-level
AutoOpenonly when implicit source lookup must remain after a justified namespace or module change. - Treat assembly-level
AutoOpenas one conditional compatibility tactic. It does not restore CLR full names or binary compatibility. - A module with only
openstatements does not re-export the opened declarations. - Namespace moves can change the meaning or legality of
private. A change tointernalbroadens accessibility and requires API review. - Namespace moves can break type aliases, extension targets, reflection names, C# callers, and compiled consumers.
Complete this step when each public change is necessary and intentional. Confirm that the experiment adds no unnecessary compatibility mechanism.
6. Prove behavior and compatibility
Validate all applicable layers:
- Build the exact project and the full solution.
- Run the repository's tests.
- Compile a minimal source consumer. Use only the documented public imports and computation-expression values.
- Compare public API/assembly metadata before and after.
- Run an already-compiled consumer when binary compatibility is required.
- Check each target framework and relevant conditional-compilation branch.
Do not infer compatibility from repository tests alone.
7. Re-measure and decide
Repeat the baseline procedure unchanged. Compare:
- median compiler and complete-build durations
- per-file type-check durations
- critical-path depth and fan-out
- variance
- source, binary, and behavioral compatibility results
Accept the refactor only when the measured gain justifies its API and maintenance costs. Report a small or noisy gain accurately. A structural experiment still gives useful evidence when you revert it.
Report
Return an evidence table with the baseline, candidate, change, run count, and variance. Link both graphs and the raw timing reports. State these results separately:
- Removed false edges
- Remaining critical path
- Proven compatibility level
- Keep, revise, or revert decision
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

