arrayview 0.12.2__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.
Files changed (91) hide show
  1. {arrayview-0.12.2 → arrayview-0.14.0}/.claude/skills/viewer-ui-checklist/SKILL.md +13 -3
  2. {arrayview-0.12.2 → arrayview-0.14.0}/.gitignore +2 -1
  3. arrayview-0.14.0/.mex/AGENTS.md +33 -0
  4. arrayview-0.14.0/.mex/ROUTER.md +76 -0
  5. arrayview-0.14.0/.mex/SETUP.md +228 -0
  6. arrayview-0.14.0/.mex/SYNC.md +62 -0
  7. arrayview-0.14.0/.mex/context/architecture.md +89 -0
  8. arrayview-0.14.0/.mex/context/conventions.md +89 -0
  9. arrayview-0.14.0/.mex/context/decisions.md +71 -0
  10. arrayview-0.14.0/.mex/context/setup.md +68 -0
  11. arrayview-0.14.0/.mex/context/stack.md +60 -0
  12. arrayview-0.14.0/.mex/patterns/INDEX.md +11 -0
  13. arrayview-0.14.0/.mex/patterns/README.md +170 -0
  14. arrayview-0.14.0/.mex/patterns/add-file-format.md +70 -0
  15. arrayview-0.14.0/.mex/patterns/debug-render.md +122 -0
  16. arrayview-0.14.0/.mex/patterns/frontend-change.md +88 -0
  17. arrayview-0.14.0/.mex/patterns/vscode-display.md +113 -0
  18. {arrayview-0.12.2 → arrayview-0.14.0}/AGENTS.md +17 -5
  19. {arrayview-0.12.2 → arrayview-0.14.0}/CONTRIBUTING.md +1 -2
  20. {arrayview-0.12.2 → arrayview-0.14.0}/PKG-INFO +1 -1
  21. {arrayview-0.12.2 → arrayview-0.14.0}/docs/display.md +1 -1
  22. {arrayview-0.12.2 → arrayview-0.14.0}/docs/viewing.md +1 -1
  23. {arrayview-0.12.2 → arrayview-0.14.0}/pyproject.toml +1 -1
  24. {arrayview-0.12.2 → arrayview-0.14.0}/scripts/release.sh +1 -1
  25. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/ARCHITECTURE.md +41 -12
  26. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_launcher.py +94 -46
  27. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_render.py +31 -26
  28. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_server.py +58 -28
  29. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_session.py +2 -2
  30. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_stdio_server.py +278 -1
  31. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_viewer.html +2848 -469
  32. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_vscode.py +264 -78
  33. arrayview-0.14.0/src/arrayview/arrayview-opener.vsix +0 -0
  34. arrayview-0.14.0/src/arrayview/gsap.min.js +11 -0
  35. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_browser.py +13 -0
  36. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_command_reachability.py +1 -1
  37. arrayview-0.14.0/tests/test_cross_mode_parametrized.py +214 -0
  38. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_interactions.py +45 -23
  39. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_mode_roundtrip.py +3 -1
  40. arrayview-0.14.0/tests/test_view_component_integration.py +381 -0
  41. arrayview-0.14.0/tests/test_view_component_unit.py +165 -0
  42. {arrayview-0.12.2 → arrayview-0.14.0}/tests/visual_smoke.py +101 -14
  43. {arrayview-0.12.2 → arrayview-0.14.0}/uv.lock +1 -1
  44. {arrayview-0.12.2 → arrayview-0.14.0}/vscode-extension/extension.js +213 -45
  45. arrayview-0.14.0/vscode-extension/package.json +53 -0
  46. arrayview-0.12.2/src/arrayview/arrayview-opener.vsix +0 -0
  47. arrayview-0.12.2/vscode-extension/package.json +0 -30
  48. {arrayview-0.12.2 → arrayview-0.14.0}/.claude/skills/invocation-consistency/SKILL.md +0 -0
  49. {arrayview-0.12.2 → arrayview-0.14.0}/.claude/skills/modes-consistency/SKILL.md +0 -0
  50. {arrayview-0.12.2 → arrayview-0.14.0}/.claude/skills/ui-consistency-audit/SKILL.md +0 -0
  51. {arrayview-0.12.2 → arrayview-0.14.0}/.claude/skills/visual-bug-fixing/SKILL.md +0 -0
  52. {arrayview-0.12.2 → arrayview-0.14.0}/.github/workflows/docs.yml +0 -0
  53. {arrayview-0.12.2 → arrayview-0.14.0}/.github/workflows/python-publish.yml +0 -0
  54. {arrayview-0.12.2 → arrayview-0.14.0}/.python-version +0 -0
  55. {arrayview-0.12.2 → arrayview-0.14.0}/LICENSE +0 -0
  56. {arrayview-0.12.2 → arrayview-0.14.0}/README.md +0 -0
  57. {arrayview-0.12.2 → arrayview-0.14.0}/docs/comparing.md +0 -0
  58. {arrayview-0.12.2 → arrayview-0.14.0}/docs/configuration.md +0 -0
  59. {arrayview-0.12.2 → arrayview-0.14.0}/docs/index.md +0 -0
  60. {arrayview-0.12.2 → arrayview-0.14.0}/docs/loading.md +0 -0
  61. {arrayview-0.12.2 → arrayview-0.14.0}/docs/logo.png +0 -0
  62. {arrayview-0.12.2 → arrayview-0.14.0}/docs/measurement.md +0 -0
  63. {arrayview-0.12.2 → arrayview-0.14.0}/docs/remote.md +0 -0
  64. {arrayview-0.12.2 → arrayview-0.14.0}/docs/stylesheets/extra.css +0 -0
  65. {arrayview-0.12.2 → arrayview-0.14.0}/matlab/arrayview.m +0 -0
  66. {arrayview-0.12.2 → arrayview-0.14.0}/mkdocs.yml +0 -0
  67. {arrayview-0.12.2 → arrayview-0.14.0}/plans/webview/LOG.md +0 -0
  68. {arrayview-0.12.2 → arrayview-0.14.0}/scripts/demo.py +0 -0
  69. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/__init__.py +0 -0
  70. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/__main__.py +0 -0
  71. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_app.py +0 -0
  72. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_config.py +0 -0
  73. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_icon.png +0 -0
  74. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_io.py +0 -0
  75. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_platform.py +0 -0
  76. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_segmentation.py +0 -0
  77. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_shell.html +0 -0
  78. {arrayview-0.12.2 → arrayview-0.14.0}/src/arrayview/_torch.py +0 -0
  79. {arrayview-0.12.2 → arrayview-0.14.0}/tests/conftest.py +0 -0
  80. {arrayview-0.12.2 → arrayview-0.14.0}/tests/make_vectorfield_test_arrays.py +0 -0
  81. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_api.py +0 -0
  82. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_cli.py +0 -0
  83. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_config.py +0 -0
  84. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_large_arrays.py +0 -0
  85. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_mode_consistency.py +0 -0
  86. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_mode_matrix.py +0 -0
  87. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_nifti_meta.py +0 -0
  88. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_rgb_pixel_art.py +0 -0
  89. {arrayview-0.12.2 → arrayview-0.14.0}/tests/test_torch.py +0 -0
  90. {arrayview-0.12.2 → arrayview-0.14.0}/tests/ui_audit.py +0 -0
  91. {arrayview-0.12.2 → 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 README stay in sync.
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 (when user-facing) `README.md` before the task is complete.
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 `README.md`** if the change is user-facing (new CLI flag, new API, new mode)
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
 
@@ -33,4 +33,5 @@ site/
33
33
  van_gogh/
34
34
  cig_presentation/
35
35
  docs/superpowers
36
- .playwright-mcp/
36
+ .playwright-mcp/
37
+ dev/TODO.md
@@ -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)