Skip to content

Commit 2ef2c30

Browse files
authored
Merge branch 'main' into develop
2 parents 8a5492e + 7dead74 commit 2ef2c30

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+4379
-948
lines changed

.pre-commit-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
repos:
2+
- repo: https://github.com/psf/black
3+
rev: 24.10.0
4+
hooks:
5+
- id: black

AGENTS.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,35 @@ Pychron is a long-lived scientific application with mixed concerns:
1919

2020
Favor conservative, low-regression changes over broad rewrites.
2121

22+
Repo Map
23+
========
24+
25+
Start with the user-facing subsystem and only expand outward as needed.
26+
27+
- application/bootstrap and plugin wiring:
28+
- `launchers/`
29+
- `pychron/applications`
30+
- `pychron/envisage`
31+
- experiment execution and scripting:
32+
- `pychron/experiment`
33+
- `pychron/pyscripts`
34+
- data reduction, processing, and pipeline work:
35+
- `pychron/pipeline`
36+
- `pychron/processing`
37+
- DVC and repository-backed persistence:
38+
- `pychron/dvc`
39+
- hardware, instruments, and control surfaces:
40+
- `pychron/hardware`
41+
- `pychron/lasers`
42+
- `pychron/extraction_line`
43+
- `pychron/spectrometer`
44+
- `pychron/furnace`
45+
- shared foundations used across many subsystems:
46+
- `pychron/core`
47+
- `pychron/database`
48+
- `pychron/paths.py`
49+
- `pychron/globals.py`
50+
2251
Working Rules
2352
=============
2453

@@ -28,28 +57,69 @@ Working Rules
2857
- Expect the repo to contain legacy modules, experimental files, and partial
2958
migrations; patch the active path you are changing instead of trying to
3059
normalize the whole tree in one pass.
60+
- If a subsystem repeatedly needs specialized guidance, add a nested
61+
`AGENTS.md` in that directory instead of overloading the root file. Only do
62+
this when the local conventions are stable and materially different from the
63+
repo-wide defaults.
3164

3265
Code Changes
3366
============
3467

3568
- Prefer focused edits over opportunistic refactors.
69+
- Add type annotations to any function you touch. If a full signature annotation
70+
would force broader churn, annotate the parameters and return value needed for
71+
the current edit and keep the rest of the change scoped.
72+
- When debugging a bug or regression, add targeted instrumentation early to
73+
confirm control flow, state transitions, inputs, and external responses before
74+
attempting speculative fixes.
3675
- When replacing debug `print()` calls in runtime code, use the repo's existing
3776
logging style:
3877
- `Loggable` subclasses use `self.debug(...)`, `self.warning(...)`, etc.
3978
- other modules typically use `new_logger(...)` or a local logger
79+
- Prefer narrow, hypothesis-driven instrumentation near the suspected failure
80+
boundary first: UI actions, task/plugin entrypoints, hardware I/O, experiment
81+
state changes, and DVC/database calls.
82+
- Remove temporary instrumentation before finishing unless it provides ongoing
83+
operational value. Do not broaden a debugging task into repo-wide logging
84+
cleanup or leave noisy logs in hot paths without justification.
4085
- Preserve `if __name__ == "__main__":` demo blocks unless the task is to remove
4186
them. Do not treat demo code as runtime code.
4287
- Keep imports modern in active Qt code. Avoid reintroducing `PySide`,
4388
`traitsui.qt4`, or `pyface.ui.qt4` in touched files.
4489
- Use ASCII unless the file already requires other characters.
4590

91+
Triage Workflow
92+
===============
93+
94+
- Identify the user-facing subsystem first, then trace inward to the smallest
95+
active module that implements the behavior.
96+
- Check for nearby tests before editing. Prefer colocated tests under
97+
`pychron/*/tests`, `test/`, or a subsystem-specific test package before
98+
reaching for broad suites.
99+
- Favor the path already exercised by launchers, plugins, tasks, or currently
100+
referenced docs. Do not normalize parallel legacy code paths unless the task
101+
explicitly requires it.
102+
- Use documentation to disambiguate architecture, startup flow, or workflow
103+
expectations, but do not widen the implementation scope just because related
104+
docs exist.
105+
- When adding a nested `AGENTS.md`, keep it limited to local setup, testing,
106+
or architectural traps. Do not duplicate root policies unless the local file
107+
is intentionally narrowing them for that subtree.
108+
46109
Testing
47110
=======
48111

49112
- Run the narrowest useful verification for the files you touched.
50113
- Good default checks:
51114
- `python -m py_compile <files>`
52115
- `python -m unittest <module>`
116+
- Testing heuristics for this repo:
117+
- prefer module-level or package-level checks before full-suite runs
118+
- search for colocated tests under `pychron/*/tests` before using aggregate
119+
runners such as `pychron/test_suite.py`
120+
- if a change touches Qt, Traits, hardware, or external services, say what is
121+
unavailable and fall back to source-level verification when runtime checks
122+
are not feasible
53123
- If a subsystem depends on Qt, Traits, or hardware services that are unavailable,
54124
say so explicitly and fall back to source-level verification.
55125

@@ -59,6 +129,11 @@ Docs And Workflow
59129
- Keep `README.md` high signal. It should explain what the repo is, where docs
60130
live, and how development works now.
61131
- Prefer documenting branch/release policy in `docs/dev_guide/`.
132+
- Useful orientation documents:
133+
- `README.md`
134+
- `docs/dev_guide/index.rst`
135+
- `docs/dev_guide/running_pychron.rst`
136+
- `docs/dev_guide/git_workflow.rst`
62137
- When release workflow changes, keep these files aligned:
63138
- `docs/dev_guide/git_workflow.rst`
64139
- `docs/dev_guide/repository_settings.rst`

architecture.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Pychron Architecture
2+
3+
## Purpose
4+
5+
This file is a fast orientation guide for the active codebase. It is not a full
6+
design spec. Use it to find the right subsystem before making changes.
7+
8+
## Top-Level Shape
9+
10+
Pychron is a Qt desktop application built on Enthought Envisage and TraitsUI.
11+
The codebase combines:
12+
13+
- application bootstrap and plugin composition
14+
- experiment execution and automation
15+
- DVC-backed persistence and repository workflows
16+
- hardware/instrument control
17+
- processing, plotting, and review tooling
18+
19+
The active runtime package is `pychron/`. Legacy and experimental paths exist;
20+
prefer the path that is currently wired into launchers, tasks, and plugins.
21+
22+
## Startup Flow
23+
24+
The main startup path is:
25+
26+
1. launcher script in `launchers/`
27+
2. launcher helper entry point
28+
3. environment/path/bootstrap setup
29+
4. `pychron.envisage.pychron_run`
30+
5. application object and plugin assembly
31+
6. Envisage task application run loop
32+
33+
The runtime tree under `~/Pychron` is now bootstrap-managed. The supported
34+
operator and developer setup flow uses:
35+
36+
- `pychron-bootstrap`
37+
- `pychron-doctor`
38+
- `python -m pychron doctor`
39+
40+
See `docs/dev_guide/running_pychron.rst` and `docs/dev_guide/installation.rst`
41+
for the current startup and install flow.
42+
43+
## Major Subsystems
44+
45+
### Envisage / application shell
46+
47+
- `pychron/envisage`
48+
- `pychron/applications`
49+
- `launchers/`
50+
51+
Owns application startup, plugin registration, task panes, browser/task shell,
52+
preferences dialogs, and shared UI wiring.
53+
54+
See `pychron/envisage/architecture.md`.
55+
56+
### Experiment execution
57+
58+
- `pychron/experiment`
59+
- `pychron/pyscripts`
60+
61+
Owns experiment queues, execution state, automated runs, scripts, queue editors,
62+
and run lifecycle coordination.
63+
64+
See `pychron/experiment/architecture.md`.
65+
66+
### DVC persistence
67+
68+
- `pychron/dvc`
69+
- parts of `pychron/entry`, `pychron/loading`, `pychron/data_mapper`
70+
71+
Owns repository-backed persistence, metadata lookup, analysis save/pull/push
72+
behavior, and DVC-facing import/export helpers.
73+
74+
See `pychron/dvc/architecture.md`.
75+
76+
### Hardware and instruments
77+
78+
- `pychron/hardware`
79+
- `pychron/extraction_line`
80+
- `pychron/lasers`
81+
- `pychron/spectrometer`
82+
- `pychron/furnace`
83+
84+
Owns device managers, controllers, remote hardware integration, and task-level
85+
instrument UIs.
86+
87+
See `pychron/hardware/architecture.md`.
88+
89+
### Processing and review
90+
91+
- `pychron/pipeline`
92+
- `pychron/processing`
93+
- `pychron/envisage/browser`
94+
95+
Owns data reduction, browser tables, plotting, review tools, and many operator
96+
analysis workflows.
97+
98+
## Shared Foundations
99+
100+
Common cross-cutting infrastructure lives in:
101+
102+
- `pychron/core`
103+
- `pychron/database`
104+
- `pychron/paths.py`
105+
- `pychron/globals.py`
106+
107+
Treat these as shared dependencies. Changes here have a larger blast radius than
108+
changes inside a task-specific package.
109+
110+
## Working Guidance
111+
112+
- Trace from the user-visible screen or command first, then narrow to the active
113+
plugin, task, manager, or editor.
114+
- Check for local `architecture.md` and `AGENTS.md` files before changing a deep
115+
subsystem.
116+
- Add instrumentation early when debugging cross-subsystem behavior, especially
117+
at plugin boundaries, queue execution boundaries, hardware I/O, and DVC save
118+
or load points.
119+
- Prefer small fixes in the active path over broad cleanup across parallel
120+
legacy implementations.

0 commit comments

Comments
 (0)