For significant changes, open a discussion in Discord or file an issue on the source repository before writing code. This avoids duplicated effort and ensures alignment with the roadmap.
Editor/
├── Domain/ Core types — no Unity dependencies, with one documented
│ exception: BuildSnapshot.Platform is a UnityEditor.BuildTarget,
│ since the alternative (a parallel BuildLens-local enum) isn't
│ worth the indirection for a value that's just stored and displayed.
├── Application/ Coordinator, engines, session manager
├── Analysis/ Build report reading, dependency graph walking, the post-build hook
├── Export/ JSON / CSV export
├── Storage/ Snapshot persistence (.blsnapshot files, index)
├── Demo/ Synthetic dataset, triggered on demand from the menu
├── Presentation/ IMGUI window and panels
│ └── Panels/
└── ToolsStudio.BuildLens.Editor.asmdef
There is no Runtime/ assembly. BuildLens is Editor-only, and an Editor-only tool has no
need to ship an empty placeholder Runtime assembly.
These rules are enforced at code review. PRs that violate them will not be merged.
Presentation → Application → Domain ← Analysis / Storage / Demo
Presentation → Export → Domain
| Layer | May Reference | Must Not Reference |
|---|---|---|
| Presentation | Application, Domain, Export | Analysis, Storage, Demo |
| Application | Domain, Analysis, Storage, Demo | Presentation, Export |
| Analysis / Storage / Demo | Domain | Presentation, Application, Export |
| Export | Domain | Presentation, Application, Analysis, Storage, Demo |
| Domain | Nothing | All other layers, Unity Editor, IO — with one narrow, documented exception (see the Repository Structure note on BuildSnapshot.Platform) |
Export is the one layer Presentation calls directly rather than through AnalysisCoordinator —
the export buttons in the Overview tab call ExportPipeline in place. This is a deliberate,
narrow exception: export is a one-shot, read-only operation on data the panel already has,
not something that needs to flow through the coordinator's state.
Panels read from AnalysisViewModel. They never call AssetDatabase, BuildReport, or any analysis engine. If a panel needs data not on the ViewModel, add it to the ViewModel and compute it in AnalysisCoordinator.
AssetDatabase.*, BuildPipeline.*, PlayerSettings.*, EditorUserBuildSettings.*, File.* belong exclusively in Analysis, Storage, Export, or Demo. The exception: EditorApplication.* is used in BuildLensWindow and AnalysisCoordinator for lifecycle management only.
Once created by FinalizeSnapshot(), no property is mutated except IsPinned — pin state
is deliberately mutable in place, since reconstructing an entire snapshot to flip one flag
would be worse than the exception.
No other class may assign properties on AnalysisViewModel. Panels call coordinator methods to change state.
| Element | Convention | Example |
|---|---|---|
| Classes | PascalCase | DependencyGraph |
| Interfaces | I + PascalCase |
Not currently used anywhere in the codebase — every type is a static or sealed class. Convention only, for if one is ever introduced. |
| Methods | PascalCase | BuildDependencyGraph() |
| Private fields | _camelCase |
_viewModel, _scroll |
| Constants | k_ prefix |
k_StorageRoot, BuildLensConstants.k_Version |
| Enum values | PascalCase | AssetType.Texture |
| Local variables | camelCase | assetNode |
- Analysis/Storage/Export/Demo methods return
(result, string error)tuples. Never throw to callers. - Application methods catch exceptions from those calls, log via
AnalysisCoordinator.Log(), and callSetFailed(). - Presentation methods wrap coordinator calls in
EditorApplication.delayCall.
Styles must not be created inside Draw() or OnGUI(). All styles are initialised in EnsureStyles(), guarded by a _stylesReady bool. No colour literal outside BuildLensStyles.cs.
- All file writes use atomic temp-then-rename.
- All file paths use
Path.Combine(). - All text I/O uses explicit
Encoding.UTF8(no BOM). - No Windows-specific path separators.
- Create
Editor/Presentation/Panels/NewPanel.csin namespaceToolsStudio.BuildLens.Editor.Presentation.Panels. - Implement the panel contract:
internal sealed class NewPanel { public void Draw(AnalysisViewModel vm) { } }. - Add a
Tabenum value inBuildLensWindow. - Instantiate the panel in
BuildLensWindow.OnEnable(). - Add the tab button to the toolbar loop.
- Add the
Draw()call to theswitchinOnGUI(). - Create a
.metafile with a stable GUID.
- Add the property to
AnalysisViewModel.cs. - Add the setter call in the appropriate
AnalysisCoordinatormethod. - Confirm no panel
Draw()method mutates the field. - If the field must survive domain reloads, persist it in
SnapshotStoreand reload it inAnalysisCoordinator.ReloadSnapshots().
- Create the class in
Editor/Analysis/,Editor/Storage/,Editor/Export/, orEditor/Demo/— whichever matches what it does. Don't add a new top-level folder for one class. - Verify no reference to
PresentationorApplicationnamespaces. - All public entry points return tuples or result objects — never throw.
- Add a unit test in
Tests/Editor/using a mock or serialised fixture. - Call the class from
AnalysisCoordinator, not from panels — unless it's a read-only, one-shot operation on data the panel already owns (the precedent isExportPipeline; see the Layer Dependency Direction note above).
Tests live in Tests/Editor/ using Unity Test Framework (EditMode). Fixtures (serialised BuildReport outputs, sample .blsnapshot files) live in Tests/Fixtures/.
Each Analysis, Storage, Export, or Demo class should have at minimum:
- A success path test with representative data.
- An error path test (null input, missing file, malformed JSON).
Domain types should have invariant tests (constructor validation, computed property accuracy).
- Fork the repository.
- Create a branch:
feature/your-featureorfix/issue-description. - Ensure all existing tests pass.
- Add tests for any new functionality.
- Update the relevant documentation files if the change affects user-visible behaviour or public API.
- Open a PR against
mainwith:- A description of the change and its motivation
- Screenshots or Console output if the change affects UI or output format
- Reference to any related Discord discussion or issue
PRs changing architecture layer boundaries, the .blsnapshot schema, or the export format require a maintainer review before merge.