arrayview 0.13.0__tar.gz → 0.14.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {arrayview-0.13.0 → arrayview-0.14.0}/.claude/skills/viewer-ui-checklist/SKILL.md +13 -3
- {arrayview-0.13.0 → arrayview-0.14.0}/.gitignore +2 -1
- arrayview-0.14.0/.mex/AGENTS.md +33 -0
- arrayview-0.14.0/.mex/ROUTER.md +76 -0
- arrayview-0.14.0/.mex/SETUP.md +228 -0
- arrayview-0.14.0/.mex/SYNC.md +62 -0
- arrayview-0.14.0/.mex/context/architecture.md +89 -0
- arrayview-0.14.0/.mex/context/conventions.md +89 -0
- arrayview-0.14.0/.mex/context/decisions.md +71 -0
- arrayview-0.14.0/.mex/context/setup.md +68 -0
- arrayview-0.14.0/.mex/context/stack.md +60 -0
- arrayview-0.14.0/.mex/patterns/INDEX.md +11 -0
- arrayview-0.14.0/.mex/patterns/README.md +170 -0
- arrayview-0.14.0/.mex/patterns/add-file-format.md +70 -0
- arrayview-0.14.0/.mex/patterns/debug-render.md +122 -0
- arrayview-0.14.0/.mex/patterns/frontend-change.md +88 -0
- arrayview-0.14.0/.mex/patterns/vscode-display.md +113 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/AGENTS.md +17 -5
- {arrayview-0.13.0 → arrayview-0.14.0}/CONTRIBUTING.md +1 -2
- {arrayview-0.13.0 → arrayview-0.14.0}/PKG-INFO +1 -1
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/display.md +1 -1
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/viewing.md +1 -1
- {arrayview-0.13.0 → arrayview-0.14.0}/pyproject.toml +1 -1
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/ARCHITECTURE.md +41 -12
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_launcher.py +15 -28
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_render.py +31 -26
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_server.py +58 -28
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_session.py +2 -2
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_viewer.html +2848 -469
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_vscode.py +205 -70
- arrayview-0.14.0/src/arrayview/arrayview-opener.vsix +0 -0
- arrayview-0.14.0/src/arrayview/gsap.min.js +11 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_browser.py +13 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_command_reachability.py +1 -1
- arrayview-0.14.0/tests/test_cross_mode_parametrized.py +214 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_interactions.py +45 -23
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_mode_roundtrip.py +3 -1
- arrayview-0.14.0/tests/test_view_component_integration.py +381 -0
- arrayview-0.14.0/tests/test_view_component_unit.py +165 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/visual_smoke.py +101 -14
- {arrayview-0.13.0 → arrayview-0.14.0}/uv.lock +1 -1
- {arrayview-0.13.0 → arrayview-0.14.0}/vscode-extension/extension.js +62 -6
- {arrayview-0.13.0 → arrayview-0.14.0}/vscode-extension/package.json +1 -1
- arrayview-0.13.0/src/arrayview/arrayview-opener.vsix +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/.claude/skills/invocation-consistency/SKILL.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/.claude/skills/modes-consistency/SKILL.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/.claude/skills/ui-consistency-audit/SKILL.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/.claude/skills/visual-bug-fixing/SKILL.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/.github/workflows/docs.yml +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/.github/workflows/python-publish.yml +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/.python-version +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/LICENSE +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/README.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/comparing.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/configuration.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/index.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/loading.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/logo.png +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/measurement.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/remote.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/docs/stylesheets/extra.css +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/matlab/arrayview.m +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/mkdocs.yml +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/plans/webview/LOG.md +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/scripts/demo.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/scripts/release.sh +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/__init__.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/__main__.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_app.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_config.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_icon.png +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_io.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_platform.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_segmentation.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_shell.html +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_stdio_server.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/src/arrayview/_torch.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/conftest.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/make_vectorfield_test_arrays.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_api.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_cli.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_config.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_large_arrays.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_mode_consistency.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_mode_matrix.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_nifti_meta.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_rgb_pixel_art.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/test_torch.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/tests/ui_audit.py +0 -0
- {arrayview-0.13.0 → arrayview-0.14.0}/vscode-extension/LICENSE +0 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: viewer-ui-checklist
|
|
3
|
-
description: Use when adding keyboard shortcuts, changing layout, or making any UI change to arrayview. Ensures visual_smoke.py, help overlay, and
|
|
3
|
+
description: Use when adding keyboard shortcuts, changing layout, or making any UI change to arrayview. Ensures visual_smoke.py, help overlay, and docs/ stay in sync.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# ArrayView UI Checklist
|
|
7
7
|
|
|
8
8
|
## Rule
|
|
9
9
|
|
|
10
|
-
Every UI change to arrayview MUST be reflected in `tests/visual_smoke.py`, the help overlay, and
|
|
10
|
+
Every UI change to arrayview MUST be reflected in `tests/visual_smoke.py`, the help overlay, and the relevant `docs/*.md` page before the task is complete.
|
|
11
|
+
|
|
12
|
+
`README.md` is intentionally minimal and stable — do **not** add per-feature shortcuts or behavior to it. User-facing docs live in `docs/` and are organized by topic (`display.md`, `viewing.md`, `comparing.md`, `loading.md`, `measurement.md`, `remote.md`, `configuration.md`).
|
|
11
13
|
|
|
12
14
|
## What counts as a UI change
|
|
13
15
|
|
|
@@ -40,8 +42,16 @@ Every UI change to arrayview MUST be reflected in `tests/visual_smoke.py`, the h
|
|
|
40
42
|
- Include a `hint` for non-obvious shortcuts
|
|
41
43
|
- Use the `docs-style` skill for formatting rules
|
|
42
44
|
|
|
43
|
-
6. **Update `
|
|
45
|
+
6. **Update the matching `docs/*.md` page** for any user-facing change. Pick the page by topic:
|
|
46
|
+
- `display.md` — colormaps, range, log scale, themes, masking, layout toggles
|
|
47
|
+
- `viewing.md` — navigation, zoom, slice/dim shortcuts, multiview, projections
|
|
48
|
+
- `comparing.md` — compare mode, overlay, diff, registration
|
|
49
|
+
- `loading.md` — file formats, CLI, Python/Julia/MATLAB API
|
|
50
|
+
- `measurement.md` — ROI, hover, pixel info
|
|
51
|
+
- `remote.md` — VS Code Remote, tunneling
|
|
52
|
+
- `configuration.md` — settings, env vars, persistence
|
|
44
53
|
- Use the `docs-style` skill for formatting rules
|
|
54
|
+
- Do **not** touch `README.md` for per-feature changes — it's intentionally stable
|
|
45
55
|
|
|
46
56
|
## Red flags — STOP
|
|
47
57
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agents
|
|
3
|
+
description: Always-loaded project anchor. Read this first. Contains project identity, non-negotiables, commands, and pointer to ROUTER.md for full context.
|
|
4
|
+
last_updated: 2026-04-13
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# arrayview
|
|
8
|
+
|
|
9
|
+
## What This Is
|
|
10
|
+
A Python package for interactively viewing multi-dimensional arrays (numpy, NIfTI, zarr, DICOM, etc.) with a FastAPI backend, a single-file HTML/JS frontend, and multi-environment display routing (Jupyter, VS Code, SSH, native window).
|
|
11
|
+
|
|
12
|
+
## Non-Negotiables
|
|
13
|
+
|
|
14
|
+
- Never split `_viewer.html` into separate files — the entire frontend is one self-contained file, no build step
|
|
15
|
+
- All heavy imports (numpy, matplotlib, nibabel, FastAPI, uvicorn) must be lazy — CLI fast path must stay near-zero cost
|
|
16
|
+
- New rendering features must be consistent across all six invocation environments (CLI, Jupyter, Julia, VS Code local, VS Code tunnel, SSH)
|
|
17
|
+
- Global state lives in `_session.py` only — `SESSIONS`, `SERVER_LOOP`, `VIEWER_SOCKETS` are never redefined elsewhere
|
|
18
|
+
- Render thread must remain a raw `threading.Thread` + `SimpleQueue`, not `concurrent.futures`
|
|
19
|
+
|
|
20
|
+
## Commands
|
|
21
|
+
|
|
22
|
+
- Test: `uv run pytest tests/`
|
|
23
|
+
- Visual smoke: `uv run pytest tests/visual_smoke.py`
|
|
24
|
+
- CLI: `uvx arrayview path/to/file.npy`
|
|
25
|
+
- Build: `uv build`
|
|
26
|
+
- Docs: `uv run mkdocs serve`
|
|
27
|
+
|
|
28
|
+
## Scaffold Growth
|
|
29
|
+
After every task: if no pattern exists for the task type you just completed, create one. If a pattern or context file is now out of date, update it. The scaffold grows from real work, not just setup. See the GROW step in `ROUTER.md` for details.
|
|
30
|
+
|
|
31
|
+
## Navigation
|
|
32
|
+
At the start of every session, read `ROUTER.md` before doing anything else.
|
|
33
|
+
For full project context, patterns, and task guidance — everything is there.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: router
|
|
3
|
+
description: Session bootstrap and navigation hub. Read at the start of every session before any task. Contains project state, routing table, and behavioural contract.
|
|
4
|
+
edges:
|
|
5
|
+
- target: context/architecture.md
|
|
6
|
+
condition: when working on system design, integrations, or understanding how components connect
|
|
7
|
+
- target: context/stack.md
|
|
8
|
+
condition: when working with specific technologies, libraries, or making tech decisions
|
|
9
|
+
- target: context/conventions.md
|
|
10
|
+
condition: when writing new code, reviewing code, or unsure about project patterns
|
|
11
|
+
- target: context/decisions.md
|
|
12
|
+
condition: when making architectural choices or understanding why something is built a certain way
|
|
13
|
+
- target: context/setup.md
|
|
14
|
+
condition: when setting up the dev environment or running the project for the first time
|
|
15
|
+
- target: patterns/INDEX.md
|
|
16
|
+
condition: when starting a task — check the pattern index for a matching pattern file
|
|
17
|
+
last_updated: 2026-04-13
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Session Bootstrap
|
|
21
|
+
|
|
22
|
+
If you haven't already read `AGENTS.md`, read it now — it contains the project identity, non-negotiables, and commands.
|
|
23
|
+
|
|
24
|
+
Then read this file fully before doing anything else in this session.
|
|
25
|
+
|
|
26
|
+
## Current Project State
|
|
27
|
+
|
|
28
|
+
**Working:**
|
|
29
|
+
- CLI (`uvx arrayview file.npy`) and Python API (`view(arr)`) — both stable
|
|
30
|
+
- All six display environments: Jupyter inline, VS Code local (Simple Browser), VS Code tunnel (stdio), Julia, native pywebview, SSH URL print
|
|
31
|
+
- File formats: `.npy`, `.npz`, `.nii`/`.nii.gz`, `.zarr`, `.h5`/`.hdf5`, `.mat`, `.tif`/`.tiff`, `.pt`/`.pth`
|
|
32
|
+
- Rendering pipeline: colormaps, complex modes (mag/phase/real/imag), mosaic, RGB/RGBA, projections (max/min/mean/std/sos/sum)
|
|
33
|
+
- Overlays: binary mask, multi-label segmentation, float heatmap with nnInteractive integration
|
|
34
|
+
- NIfTI spatial metadata display, RAS resampling
|
|
35
|
+
- VS Code extension v0.14.0 — stable window ID via `EnvironmentVariableCollection`
|
|
36
|
+
- Colorbar refactor: `ColorBar` JS class partially migrated (in progress)
|
|
37
|
+
|
|
38
|
+
**Not yet built:**
|
|
39
|
+
- Independent split view for mismatched-shape arrays (designed, shelved — see `project_independent_split_view.md` memory)
|
|
40
|
+
- Smooth immersive transition during continuous trackpad zoom (deferred — see memory)
|
|
41
|
+
- Admin/config UI — config is file-based (`~/.arrayview/config.toml`) only
|
|
42
|
+
|
|
43
|
+
**Known issues:**
|
|
44
|
+
- White flicker on macOS native window before loading animation appears (minor, tracked in `dev/TODO.md`)
|
|
45
|
+
- ColorBar class refactor is partially complete — some colorbars still use legacy inline code
|
|
46
|
+
|
|
47
|
+
## Routing Table
|
|
48
|
+
|
|
49
|
+
Load the relevant file based on the current task. Always load `context/architecture.md` first if not already in context this session.
|
|
50
|
+
|
|
51
|
+
| Task type | Load |
|
|
52
|
+
|-----------|------|
|
|
53
|
+
| Understanding how the system works | `context/architecture.md` |
|
|
54
|
+
| Working with a specific technology | `context/stack.md` |
|
|
55
|
+
| Writing or reviewing code | `context/conventions.md` |
|
|
56
|
+
| Making a design decision | `context/decisions.md` |
|
|
57
|
+
| Setting up or running the project | `context/setup.md` |
|
|
58
|
+
| Editing `_viewer.html` (frontend) | `patterns/frontend-change.md` |
|
|
59
|
+
| Adding a new file format | `patterns/add-file-format.md` |
|
|
60
|
+
| VS Code display / IPC issues | `patterns/vscode-display.md` |
|
|
61
|
+
| Visual bugs / render artifacts | `patterns/debug-render.md` |
|
|
62
|
+
| Any specific task | Check `patterns/INDEX.md` for a matching pattern |
|
|
63
|
+
|
|
64
|
+
## Behavioural Contract
|
|
65
|
+
|
|
66
|
+
For every task, follow this loop:
|
|
67
|
+
|
|
68
|
+
1. **CONTEXT** — Load the relevant context file(s) from the routing table above. Check `patterns/INDEX.md` for a matching pattern. If one exists, follow it. Narrate what you load: "Loading architecture context..."
|
|
69
|
+
2. **BUILD** — Do the work. If a pattern exists, follow its Steps. If you are about to deviate from an established pattern, say so before writing any code — state the deviation and why.
|
|
70
|
+
3. **VERIFY** — Load `context/conventions.md` and run the Verify Checklist item by item. State each item and whether the output passes. Do not summarise — enumerate explicitly.
|
|
71
|
+
4. **DEBUG** — If verification fails or something breaks, check `patterns/INDEX.md` for a debug pattern. Follow it. Fix the issue and re-run VERIFY.
|
|
72
|
+
5. **GROW** — After completing the task:
|
|
73
|
+
- If no pattern exists for this task type, create one in `patterns/` using the format in `patterns/README.md`. Add it to `patterns/INDEX.md`. Flag it: "Created `patterns/<name>.md` from this session."
|
|
74
|
+
- If a pattern exists but you deviated from it or discovered a new gotcha, update it with what you learned.
|
|
75
|
+
- If any `context/` file is now out of date because of this work, update it surgically — do not rewrite entire files.
|
|
76
|
+
- Update the "Current Project State" section above if the work was significant.
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Setup — Populate This Scaffold
|
|
2
|
+
|
|
3
|
+
This file contains the prompts to populate the scaffold. It is NOT the dev environment setup — for that, see `context/setup.md` after population.
|
|
4
|
+
|
|
5
|
+
This scaffold is currently empty. Follow the steps below to populate it for your project.
|
|
6
|
+
|
|
7
|
+
## Recommended: Use setup.sh
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
.mex/setup.sh
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The script handles everything automatically:
|
|
14
|
+
1. Detects your project state (existing codebase, fresh project, or partial)
|
|
15
|
+
2. Asks which AI tool you use and copies the right config file
|
|
16
|
+
3. Pre-scans your codebase with `mex init` to build a structured brief (~5-8k tokens vs ~50k from AI exploration)
|
|
17
|
+
4. Builds and runs the population prompt — or prints it for manual paste
|
|
18
|
+
|
|
19
|
+
If you want to populate manually instead, use the prompts below.
|
|
20
|
+
|
|
21
|
+
## Detecting Your State
|
|
22
|
+
|
|
23
|
+
**Existing codebase?** Follow Option A.
|
|
24
|
+
**Fresh project, nothing built yet?** Follow Option B.
|
|
25
|
+
**Partially built?** Follow Option A — the agent will flag empty slots it cannot fill yet.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Option A — Existing Codebase
|
|
30
|
+
|
|
31
|
+
Paste the following prompt into your agent:
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
**SETUP PROMPT — copy everything between the lines:**
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
You are going to populate an AI context scaffold for this project.
|
|
39
|
+
The scaffold lives in the root of this repository.
|
|
40
|
+
|
|
41
|
+
Read the following files in order before doing anything else:
|
|
42
|
+
1. ROUTER.md — understand the scaffold structure
|
|
43
|
+
2. context/architecture.md — read the annotation comments to understand what belongs there
|
|
44
|
+
3. context/stack.md — same
|
|
45
|
+
4. context/conventions.md — same
|
|
46
|
+
5. context/decisions.md — same
|
|
47
|
+
6. context/setup.md — same
|
|
48
|
+
|
|
49
|
+
Then explore this codebase:
|
|
50
|
+
- Read the main entry point(s)
|
|
51
|
+
- Read the folder structure
|
|
52
|
+
- Read 2-3 representative files from each major layer
|
|
53
|
+
- Read any existing README or documentation
|
|
54
|
+
|
|
55
|
+
PASS 1 — Populate knowledge files:
|
|
56
|
+
|
|
57
|
+
Populate each context/ file by replacing the annotation comments
|
|
58
|
+
with real content from this codebase. Follow the annotation instructions exactly.
|
|
59
|
+
For each slot:
|
|
60
|
+
- Use the actual names, patterns, and structures from this codebase
|
|
61
|
+
- Do not use generic examples
|
|
62
|
+
- Do not leave any slot empty — if you cannot determine the answer,
|
|
63
|
+
write "[TO DETERMINE]" and explain what information is needed
|
|
64
|
+
- Keep length within the guidance given in each annotation
|
|
65
|
+
|
|
66
|
+
Then assess: does this project have domains complex enough that cramming
|
|
67
|
+
them into architecture.md would make it too long or too shallow?
|
|
68
|
+
If yes, create additional domain-specific context files in context/.
|
|
69
|
+
Examples: a project with a complex auth system gets context/auth.md.
|
|
70
|
+
A data pipeline gets context/ingestion.md. A project with Stripe gets
|
|
71
|
+
context/payments.md. Use the same YAML frontmatter format (name,
|
|
72
|
+
description, triggers, edges, last_updated). Only create these for
|
|
73
|
+
domains that have real depth — not for simple integrations that fit
|
|
74
|
+
in a few lines of architecture.md.
|
|
75
|
+
|
|
76
|
+
After populating context/ files, update ROUTER.md:
|
|
77
|
+
- Fill in the Current Project State section based on what you found
|
|
78
|
+
- Add rows to the routing table for any domain-specific context files you created
|
|
79
|
+
|
|
80
|
+
Update AGENTS.md:
|
|
81
|
+
- Fill in the project name, one-line description, non-negotiables, and commands
|
|
82
|
+
|
|
83
|
+
PASS 2 — Generate starter patterns:
|
|
84
|
+
|
|
85
|
+
Read patterns/README.md for the format and categories.
|
|
86
|
+
|
|
87
|
+
Generate 3-5 starter patterns for the most common and most dangerous task
|
|
88
|
+
types in this project. Focus on:
|
|
89
|
+
- The 1-2 tasks a developer does most often (e.g., add endpoint, add component)
|
|
90
|
+
- The 1-2 integrations with the most non-obvious gotchas
|
|
91
|
+
- 1 debug pattern for the most common failure boundary
|
|
92
|
+
|
|
93
|
+
Each pattern should be specific to this project — real file paths, real gotchas,
|
|
94
|
+
real verify steps derived from the code you read in Pass 1.
|
|
95
|
+
Use the format in patterns/README.md. Name descriptively (e.g., add-endpoint.md).
|
|
96
|
+
|
|
97
|
+
Do NOT try to generate a pattern for every possible task type. The scaffold
|
|
98
|
+
grows incrementally — the behavioural contract (step 5: GROW) will create
|
|
99
|
+
new patterns from real work as the project evolves. Setup just seeds the most
|
|
100
|
+
critical ones.
|
|
101
|
+
|
|
102
|
+
After generating patterns, update patterns/INDEX.md with a row for each
|
|
103
|
+
pattern file you created. For multi-section patterns, add one row per task
|
|
104
|
+
section using anchor links (see INDEX.md annotation for format).
|
|
105
|
+
|
|
106
|
+
PASS 3 — Wire the web:
|
|
107
|
+
|
|
108
|
+
Re-read every file you just wrote (context/ files, pattern files, ROUTER.md).
|
|
109
|
+
For each file, add or update the `edges` array in the YAML frontmatter.
|
|
110
|
+
Each edge should point to another scaffold file that is meaningfully related,
|
|
111
|
+
with a `condition` explaining when an agent should follow that edge.
|
|
112
|
+
|
|
113
|
+
Rules for edges:
|
|
114
|
+
- Every context/ file should have at least 2 edges
|
|
115
|
+
- Every pattern file should have at least 1 edge (usually to the relevant context file)
|
|
116
|
+
- Edges should be bidirectional where it makes sense (if A links to B, consider B linking to A)
|
|
117
|
+
- Use relative paths (e.g., context/stack.md, patterns/add-endpoint.md)
|
|
118
|
+
- Pattern files can edge to other patterns (e.g., debug pattern → related task pattern)
|
|
119
|
+
|
|
120
|
+
Important: only write content derived from the codebase.
|
|
121
|
+
Do not include system-injected text (dates, reminders, etc.)
|
|
122
|
+
in any scaffold file.
|
|
123
|
+
|
|
124
|
+
When done, confirm which files were populated and flag any slots
|
|
125
|
+
you could not fill with confidence.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Option B — Fresh Project
|
|
131
|
+
|
|
132
|
+
Paste the following prompt into your agent:
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
**SETUP PROMPT — copy everything between the lines:**
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
You are going to populate an AI context scaffold for a project that
|
|
140
|
+
is just starting. Nothing is built yet.
|
|
141
|
+
|
|
142
|
+
Read the following files in order before doing anything else:
|
|
143
|
+
1. ROUTER.md — understand the scaffold structure
|
|
144
|
+
2. All files in context/ — read the annotation comments in each
|
|
145
|
+
|
|
146
|
+
Then ask me the following questions one section at a time.
|
|
147
|
+
Wait for my answer before moving to the next section:
|
|
148
|
+
|
|
149
|
+
1. What does this project do? (one sentence)
|
|
150
|
+
2. What are the hard rules — things that must never happen in this codebase?
|
|
151
|
+
3. What is the tech stack? (language, framework, database, key libraries)
|
|
152
|
+
4. Why did you choose this stack over alternatives?
|
|
153
|
+
5. How will the major pieces connect? Describe the flow of a typical request/action.
|
|
154
|
+
6. What patterns do you want to enforce from day one?
|
|
155
|
+
7. What are you deliberately NOT building or using?
|
|
156
|
+
|
|
157
|
+
After I answer, populate the context/ files based on my answers.
|
|
158
|
+
For any slot you cannot fill yet, write "[TO BE DETERMINED]" and note
|
|
159
|
+
what needs to be decided before it can be filled.
|
|
160
|
+
|
|
161
|
+
Then assess: based on my answers, does this project have domains complex
|
|
162
|
+
enough that cramming them into architecture.md would make it too long
|
|
163
|
+
or too shallow? If yes, create additional domain-specific context files
|
|
164
|
+
in context/. Examples: a project with a complex auth system gets
|
|
165
|
+
context/auth.md. A data pipeline gets context/ingestion.md. A project
|
|
166
|
+
with Stripe gets context/payments.md. Use the same YAML frontmatter
|
|
167
|
+
format (name, description, triggers, edges, last_updated). Only create
|
|
168
|
+
these for domains that have real depth — not for simple integrations
|
|
169
|
+
that fit in a few lines of architecture.md. For fresh projects, mark
|
|
170
|
+
domain-specific unknowns with "[TO BE DETERMINED — populate after first
|
|
171
|
+
implementation]".
|
|
172
|
+
|
|
173
|
+
Update ROUTER.md current state to reflect that this is a new project.
|
|
174
|
+
Add rows to the routing table for any domain-specific context files you created.
|
|
175
|
+
Update AGENTS.md with the project name, description, non-negotiables, and commands.
|
|
176
|
+
|
|
177
|
+
Read patterns/README.md for the format and categories.
|
|
178
|
+
|
|
179
|
+
Generate 2-3 starter patterns for the most obvious task types you can
|
|
180
|
+
anticipate for this stack. Focus on the tasks a developer will do first.
|
|
181
|
+
Mark unknowns with "[VERIFY AFTER FIRST IMPLEMENTATION]".
|
|
182
|
+
|
|
183
|
+
Do NOT try to anticipate every possible pattern. The scaffold grows
|
|
184
|
+
incrementally — the behavioural contract (step 5: GROW) will create
|
|
185
|
+
new patterns from real work as the project evolves. Setup just seeds
|
|
186
|
+
the most critical ones.
|
|
187
|
+
|
|
188
|
+
After generating patterns, update patterns/INDEX.md with a row for each
|
|
189
|
+
pattern file you created.
|
|
190
|
+
|
|
191
|
+
PASS 3 — Wire the web:
|
|
192
|
+
|
|
193
|
+
Re-read every file you just wrote (context/ files, pattern files, ROUTER.md).
|
|
194
|
+
For each file, add or update the `edges` array in the YAML frontmatter.
|
|
195
|
+
Each edge should point to another scaffold file that is meaningfully related,
|
|
196
|
+
with a `condition` explaining when an agent should follow that edge.
|
|
197
|
+
|
|
198
|
+
Rules for edges:
|
|
199
|
+
- Every context/ file should have at least 2 edges
|
|
200
|
+
- Every pattern file should have at least 1 edge
|
|
201
|
+
- Edges should be bidirectional where it makes sense
|
|
202
|
+
- Use relative paths (e.g., context/stack.md, patterns/add-endpoint.md)
|
|
203
|
+
|
|
204
|
+
Important: only write content derived from your answers.
|
|
205
|
+
Do not include system-injected text (dates, reminders, etc.)
|
|
206
|
+
in any scaffold file.
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## After Setup
|
|
212
|
+
|
|
213
|
+
**Verify** by starting a fresh session and asking your agent:
|
|
214
|
+
"Read `.mex/ROUTER.md` and tell me what you now know about this project."
|
|
215
|
+
|
|
216
|
+
A well-populated scaffold should give the agent enough to:
|
|
217
|
+
- Describe the architecture without looking at code
|
|
218
|
+
- Name the non-negotiable conventions
|
|
219
|
+
- Know which files to load for any given task type
|
|
220
|
+
- Know which patterns exist for common task types
|
|
221
|
+
|
|
222
|
+
## Keeping It Fresh
|
|
223
|
+
|
|
224
|
+
Once the scaffold is populated, use these to keep it aligned with your codebase:
|
|
225
|
+
|
|
226
|
+
- **`mex check`** — detect drift (zero tokens, zero AI)
|
|
227
|
+
- **`.mex/sync.sh`** — interactive drift check + targeted or full resync
|
|
228
|
+
- **`mex watch`** — auto drift score after every commit
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Sync — Realign This Scaffold
|
|
2
|
+
|
|
3
|
+
## Recommended: Use sync.sh
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
.mex/sync.sh
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The script runs drift detection first, shows you exactly what's wrong, then offers:
|
|
10
|
+
1. **Targeted sync** — AI fixes only the flagged files (fastest, cheapest)
|
|
11
|
+
2. **Full resync** — AI re-reads everything and updates all scaffold files
|
|
12
|
+
3. **Prompt export** — shows the prompts for manual paste
|
|
13
|
+
4. **Exit** — fix it yourself
|
|
14
|
+
|
|
15
|
+
## Quick Check
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
mex check # full drift report
|
|
19
|
+
mex check --quiet # one-liner: "drift score 85/100 (1 error)"
|
|
20
|
+
mex sync --dry-run # preview targeted fix prompts
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Manual Resync
|
|
24
|
+
|
|
25
|
+
If you prefer to paste a prompt manually, or don't have the CLI built:
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
**SYNC PROMPT — copy everything between the lines:**
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
You are going to resync the AI context scaffold for this project.
|
|
33
|
+
The scaffold may be out of date — the codebase has changed since it was last populated.
|
|
34
|
+
|
|
35
|
+
First, read all files in context/ to understand the current scaffold state.
|
|
36
|
+
Then explore what has changed in the codebase since the scaffold was last updated.
|
|
37
|
+
Check the last_updated dates in the YAML frontmatter of each file.
|
|
38
|
+
|
|
39
|
+
For each context/ file:
|
|
40
|
+
1. Compare the current scaffold content to the actual codebase
|
|
41
|
+
2. Identify what has changed, been added, or been removed
|
|
42
|
+
3. Update the file to reflect the current state
|
|
43
|
+
|
|
44
|
+
Critical rules for updating:
|
|
45
|
+
- Use surgical, targeted edits — NOT full file rewrites. Read the existing content,
|
|
46
|
+
identify what changed, and update only those sections.
|
|
47
|
+
- PRESERVE YAML frontmatter structure. Never delete or rewrite the entire frontmatter block.
|
|
48
|
+
Edit individual fields only. The edges, triggers, name, and description fields must
|
|
49
|
+
survive every sync. If you need to update edges, add or remove individual entries —
|
|
50
|
+
do not replace the entire array.
|
|
51
|
+
- In context/decisions.md: NEVER delete existing decisions.
|
|
52
|
+
If a decision has changed, mark the old entry as "Superseded by [new decision title]"
|
|
53
|
+
and add the new decision above it with today's date.
|
|
54
|
+
- In all other files: update content to reflect current reality
|
|
55
|
+
- Update last_updated in the YAML frontmatter of every file you change
|
|
56
|
+
- After updating each file, update ROUTER.md Current Project State
|
|
57
|
+
|
|
58
|
+
When done, report:
|
|
59
|
+
- Which files were updated and what changed
|
|
60
|
+
- Any decisions that were superseded
|
|
61
|
+
- Any slots that could not be filled with confidence
|
|
62
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architecture
|
|
3
|
+
description: How the major pieces of arrayview connect and flow. Load when working on system design, integrations, or understanding how components interact.
|
|
4
|
+
triggers:
|
|
5
|
+
- "architecture"
|
|
6
|
+
- "system design"
|
|
7
|
+
- "how does X connect to Y"
|
|
8
|
+
- "integration"
|
|
9
|
+
- "flow"
|
|
10
|
+
- "display routing"
|
|
11
|
+
- "server mode"
|
|
12
|
+
edges:
|
|
13
|
+
- target: context/stack.md
|
|
14
|
+
condition: when specific technology details are needed
|
|
15
|
+
- target: context/decisions.md
|
|
16
|
+
condition: when understanding why the architecture is structured this way
|
|
17
|
+
- target: patterns/vscode-display.md
|
|
18
|
+
condition: when working on VS Code display routing or IPC
|
|
19
|
+
- target: patterns/frontend-change.md
|
|
20
|
+
condition: when working on the frontend viewer
|
|
21
|
+
last_updated: 2026-04-13
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Architecture
|
|
25
|
+
|
|
26
|
+
## System Overview
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
CLI / Python API (arrayview file.npy OR view(arr))
|
|
30
|
+
↓
|
|
31
|
+
_launcher.py — detects environment, starts server, opens display
|
|
32
|
+
├─ _platform.py environment detection (Jupyter/VSCode/SSH/Julia/native)
|
|
33
|
+
└─ _vscode.py VS Code extension install, signal-file IPC, browser open
|
|
34
|
+
|
|
35
|
+
Server (one of two transport modes):
|
|
36
|
+
├─ Network mode: FastAPI (_server.py) + uvicorn → HTTP/WebSocket on localhost:PORT
|
|
37
|
+
└─ Stdio mode: _stdio_server.py → JSON+binary over stdin/stdout (VS Code tunnel)
|
|
38
|
+
|
|
39
|
+
Server internals (both modes):
|
|
40
|
+
├─ _session.py Session objects, SESSIONS dict, render thread, prefetch, cache budgets
|
|
41
|
+
├─ _render.py extract_slice → apply_complex_mode → apply_colormap_rgba → PNG
|
|
42
|
+
└─ _io.py load_data() for .npy/.npz/.nii/.zarr/.h5/.mat/.tiff/.pt
|
|
43
|
+
|
|
44
|
+
Frontend:
|
|
45
|
+
└─ _viewer.html Single ~15k-line self-contained HTML/CSS/JS file
|
|
46
|
+
← binary RGBA frames over WebSocket / postMessage
|
|
47
|
+
→ slice index, colormap, mode commands back to server
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Key Components
|
|
51
|
+
|
|
52
|
+
- **`_launcher.py`** (2817 lines) — Main entry point. CLI parser, `view()` API, `ViewHandle`, server lifecycle (port detection, background thread start), SSH relay, demo arrays, file watching. Imports `_server` and `uvicorn` lazily to keep CLI fast path cheap.
|
|
53
|
+
- **`_server.py`** (3258 lines) — FastAPI app. All REST endpoints (`/load`, `/reload`, `/seg/*`, `/resample_ras`, …) and WebSocket handler (`/ws/{sid}`). Reads from `Session` objects in `_session.SESSIONS`.
|
|
54
|
+
- **`_viewer.html`** (~15,600 lines) — The entire frontend. CSS dark theme + JS viewer state machine in a single file. No build step. Organized by `/* ── Section ── */` comment separators. Receives binary RGBA frames, renders to Canvas.
|
|
55
|
+
- **`_session.py`** — `Session` class (LRU raw/rgba/mosaic caches, preload state, vfield, spatial_meta), global state (SESSIONS dict, SERVER_LOOP, VIEWER_SOCKETS), dedicated render thread, prefetch pool.
|
|
56
|
+
- **`_render.py`** — `extract_slice` → `apply_complex_mode` → `apply_colormap_rgba` → `render_rgba`. Also handles `render_mosaic`, `render_rgb_rgba`, overlay compositing. Colormap LUTs built lazily via `_init_luts()`.
|
|
57
|
+
- **`_platform.py`** — Environment detection: `_in_jupyter()`, `_in_vscode_terminal()`, `_is_vscode_remote()`, `_in_vscode_tunnel()`, `_can_native_window()`, `_is_julia_env()`. Includes ancestor-process walk to recover env vars stripped by `uv run`.
|
|
58
|
+
- **`_vscode.py`** — VS Code extension auto-install (VSIX bundled in package), signal-file IPC (`open-request-v0900.json`), shared-memory IPC, `EnvironmentVariableCollection` window ID (stable across uv run env stripping).
|
|
59
|
+
- **`_stdio_server.py`** (791 lines) — Alternative transport for VS Code direct webview. Reads JSON requests from stdin, writes binary RGBA frames to stdout. Spawned as subprocess by the VS Code extension.
|
|
60
|
+
- **`_io.py`** — `load_data(filepath)` dispatcher. Handles lazy vs eager loading per format. `.nii.gz` is always materialized (gzip not seekable). `.npy` uses `mmap_mode="r"`.
|
|
61
|
+
|
|
62
|
+
## Display Routing
|
|
63
|
+
|
|
64
|
+
| Environment | Display method | Server mode |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| Jupyter | Inline iframe | network |
|
|
67
|
+
| VS Code local terminal | Simple Browser (signal-file IPC) | network |
|
|
68
|
+
| VS Code tunnel (remote) | Direct webview via stdio | stdio |
|
|
69
|
+
| Julia | System browser | network |
|
|
70
|
+
| CLI / Python script (macOS/Win) | Native pywebview window | network |
|
|
71
|
+
| SSH (no VS Code) | Prints URL; VS Code ext tries TCP relay | network |
|
|
72
|
+
|
|
73
|
+
Detection lives in `_platform.py`. Opening logic in `_launcher.py` and `_vscode.py`.
|
|
74
|
+
|
|
75
|
+
## External Dependencies
|
|
76
|
+
|
|
77
|
+
- **FastAPI + uvicorn** — HTTP/WebSocket server. Imported lazily from `_server_mod()` in `_launcher.py` to save ~175 ms on CLI fast path (server already running).
|
|
78
|
+
- **nibabel** — NIfTI loading. Lazy import inside `_io._nib()`. `.nii.gz` volumes are materialized up front; `.nii` uses mmap.
|
|
79
|
+
- **matplotlib + qmricolors** — Colormap LUTs. Both deferred until first render via `_init_luts()`. `qmricolors` registers `lipari` and `navia` colormaps.
|
|
80
|
+
- **pywebview** — Native window rendering on macOS/Windows/Linux. Launched in a fresh subprocess (via `_open_webview`) to avoid multiprocessing bootstrap issues from Jupyter.
|
|
81
|
+
- **zarr** — Lazy array access for `.zarr` files. Used directly; no abstraction layer.
|
|
82
|
+
|
|
83
|
+
## What Does NOT Exist Here
|
|
84
|
+
|
|
85
|
+
- No database — all state is in-memory (`SESSIONS` dict) and dies with the process.
|
|
86
|
+
- No authentication — server binds to localhost only; no access control.
|
|
87
|
+
- No async rendering — render thread is a dedicated `threading.Thread` pulling from a `SimpleQueue`; deliberately not `concurrent.futures` (immune to interpreter-shutdown executor cleanup).
|
|
88
|
+
- No build step for the frontend — `_viewer.html` is a single file edited directly.
|
|
89
|
+
- No separate admin / management interface — `_config.py` reads `~/.arrayview/config.toml` directly.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: conventions
|
|
3
|
+
description: How code is written in arrayview — naming, structure, lazy imports, and frontend organization. Load when writing new code or reviewing existing code.
|
|
4
|
+
triggers:
|
|
5
|
+
- "convention"
|
|
6
|
+
- "pattern"
|
|
7
|
+
- "naming"
|
|
8
|
+
- "style"
|
|
9
|
+
- "how should I"
|
|
10
|
+
- "what's the right way"
|
|
11
|
+
- "lazy import"
|
|
12
|
+
edges:
|
|
13
|
+
- target: context/architecture.md
|
|
14
|
+
condition: when a convention depends on understanding the system structure
|
|
15
|
+
- target: context/stack.md
|
|
16
|
+
condition: when the convention is library-specific
|
|
17
|
+
- target: patterns/frontend-change.md
|
|
18
|
+
condition: when writing frontend (HTML/CSS/JS) code
|
|
19
|
+
last_updated: 2026-04-13
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Conventions
|
|
23
|
+
|
|
24
|
+
## Naming
|
|
25
|
+
|
|
26
|
+
- **Module files** — all private, prefixed with `_` (`_launcher.py`, `_render.py`, `_server.py`). Only `__init__.py` and `__main__.py` are public entry points.
|
|
27
|
+
- **Functions** — `snake_case`, internal helpers prefixed with `_` (e.g. `_compute_vmin_vmax`, `_in_jupyter`)
|
|
28
|
+
- **Constants** — `SCREAMING_SNAKE_CASE` for module-level constants (`SESSIONS`, `LUTS`, `COLORMAPS`, `HEAVY_OP_LIMIT_BYTES`)
|
|
29
|
+
- **Classes** — `PascalCase` (`Session`, `ViewHandle`, `TrainingMonitor`, `_LazyMod`)
|
|
30
|
+
- **Frontend section separators** — `/* ── Section Name ── */` in CSS, `// ── Section Name ──` in JS (double-dash with spaces, em-dashes)
|
|
31
|
+
|
|
32
|
+
## Structure
|
|
33
|
+
|
|
34
|
+
- **Lazy imports everywhere** — any import that costs >10 ms must be deferred. Pattern: module-level `_cache = None` + accessor function (see `_server_mod()`, `_uvicorn()`, `_nib()`, `_init_luts()`). The CLI fast path (server already running) must stay near-zero cost.
|
|
35
|
+
- **Global state lives in `_session.py`** — `SESSIONS`, `SERVER_LOOP`, `VIEWER_SOCKETS`, `SHELL_SOCKETS`. Other modules import these by name, never redefine them.
|
|
36
|
+
- **Render pipeline is pure functions** — `_render.py` exports stateless functions that take `session` + parameters. No class hierarchy.
|
|
37
|
+
- **One HTML file for the entire frontend** — all CSS and JS live in `_viewer.html`. Do not split into separate files.
|
|
38
|
+
- **Tests live in `tests/`** — not next to source files. Visual/browser tests use playwright and are marked `@pytest.mark.browser`.
|
|
39
|
+
- **All file-format loading goes through `_io.load_data(filepath)`** — no direct format imports in `_server.py` or `_launcher.py`.
|
|
40
|
+
|
|
41
|
+
## Patterns
|
|
42
|
+
|
|
43
|
+
**Lazy module import pattern** (used for all heavy dependencies):
|
|
44
|
+
```python
|
|
45
|
+
# At module level
|
|
46
|
+
_nib_mod = None
|
|
47
|
+
|
|
48
|
+
def _nib():
|
|
49
|
+
global _nib_mod
|
|
50
|
+
if _nib_mod is None:
|
|
51
|
+
import nibabel
|
|
52
|
+
_nib_mod = nibabel
|
|
53
|
+
return _nib_mod
|
|
54
|
+
|
|
55
|
+
# Usage: _nib().load(filepath) — never `import nibabel` at top level
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Session cache pattern** (LRU via `OrderedDict`):
|
|
59
|
+
```python
|
|
60
|
+
key = (dim_x, dim_y, key_idx)
|
|
61
|
+
if key in session.raw_cache:
|
|
62
|
+
session.raw_cache.move_to_end(key) # LRU update
|
|
63
|
+
return session.raw_cache[key]
|
|
64
|
+
# ... compute result ...
|
|
65
|
+
session.raw_cache[key] = result
|
|
66
|
+
session._raw_bytes += result.nbytes
|
|
67
|
+
while session._raw_bytes > session.RAW_CACHE_BYTES and session.raw_cache:
|
|
68
|
+
_, v = session.raw_cache.popitem(last=False)
|
|
69
|
+
session._raw_bytes -= v.nbytes
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Environment detection order** (in `_platform.detect_environment()`):
|
|
73
|
+
```
|
|
74
|
+
jupyter → vscode → julia → ssh → terminal
|
|
75
|
+
```
|
|
76
|
+
Always check in this priority order. Never short-circuit.
|
|
77
|
+
|
|
78
|
+
**Float rendering convention** — slices are always converted to `np.float32` before applying colormap. RGB uint8 arrays skip colormap and go directly to RGBA. Complex arrays are transformed by `apply_complex_mode()` before any colormap step.
|
|
79
|
+
|
|
80
|
+
## Verify Checklist
|
|
81
|
+
|
|
82
|
+
Before presenting any code change:
|
|
83
|
+
- [ ] New heavy imports are lazy (wrapped in a `_mod = None` / accessor function pattern)
|
|
84
|
+
- [ ] Any new `Session` field is initialized in `Session.__init__` and cleared in `reset_caches()` if it's cache-related
|
|
85
|
+
- [ ] New file format support goes through `_io.load_data()` and adds the extension to `_SUPPORTED_EXTS`
|
|
86
|
+
- [ ] Frontend changes are in `_viewer.html` only — no new JS/CSS files
|
|
87
|
+
- [ ] New rendering functions follow the `extract_slice → apply_complex_mode → apply_colormap_rgba` pipeline order
|
|
88
|
+
- [ ] Environment detection changes go in `_platform.py`, not inline in `_launcher.py` or `_vscode.py`
|
|
89
|
+
- [ ] Cross-mode consistency: any new visual feature verified in all six invocation environments (see `invocation-consistency` skill)
|