|
| 1 | +# Contributing to PanLL |
| 2 | + |
| 3 | +## Why These Tools? |
| 4 | + |
| 5 | +Before you dive in, it helps to understand *why* PanLL uses the stack it |
| 6 | +does. These aren’t arbitrary preferences — they’re lessons learned from |
| 7 | +building a 14-panel stateful application. |
| 8 | + |
| 9 | +**AffineScript instead of TypeScript** — PanLL has 26,000+ lines of |
| 10 | +state management across 14 panels. TypeScript’s structural type system |
| 11 | +means `any` leaks are always one cast away, and discriminated unions |
| 12 | +require manual type guards that are easy to forget. ReScript’s sound |
| 13 | +type system means if it compiles, the types are correct — no escape |
| 14 | +hatches, no `as` `unknown` `as`, no runtime type errors. Exhaustive |
| 15 | +pattern matching on variant types caught dozens of “missing case” bugs |
| 16 | +during the panel expansion. See |
| 17 | +<a href="https://rescript-lang.org" class="org">rescript-lang</a>. |
| 18 | + |
| 19 | +**Rust + Gossamer instead of Electron** — PanLL’s release binary is ~5 |
| 20 | +MB. An equivalent Electron app would be 100+ MB (shipping an entire |
| 21 | +Chromium). The Rust backend runs through Gossamer (Zig + WebKitGTK), a |
| 22 | +lightweight container-friendly webview shell. Filesystem watching, git |
| 23 | +blame parsing, and HTTP clients run with no garbage collector pauses — |
| 24 | +important when 106 panels are subscribed to live events. PanLL |
| 25 | +originally used Tauri 2.0 but migrated to Gossamer for better container |
| 26 | +support and tighter integration with the hyperpolymath stack. |
| 27 | + |
| 28 | +**Deno instead of npm/Node** — No `node_modules` directory (1,200\ |
| 29 | +transitive deps for a typical Node project). Built-in test runner. |
| 30 | +Secure-by-default permissions. ReScript and Tailwind run via `npm:` |
| 31 | +specifiers in `deno.json`; there is no `package.json` and no npm CLI is |
| 32 | +invoked. |
| 33 | + |
| 34 | +**Elixir/BEAM for middleware** — BEAM’s supervision trees mean a |
| 35 | +crashing backend connection restarts itself without taking down the |
| 36 | +whole panel surface. Pattern matching on messages is the same philosophy |
| 37 | +as ReScript’s TEA on the frontend. |
| 38 | + |
| 39 | +**Julia for data processing** — When batch analysis needs actual numeric |
| 40 | +performance. Python’s GIL means “import numpy and pray”; Julia’s |
| 41 | +multiple dispatch compiles to LLVM native code for every combination of |
| 42 | +argument types. |
| 43 | + |
| 44 | +If you’re coming from TypeScript/React, the biggest mental shift is TEA |
| 45 | +(The Elm Architecture): state changes are pure functions, side effects |
| 46 | +are commands, and the compiler enforces exhaustiveness everywhere. It’s |
| 47 | +more explicit than hooks, but after the first day you’ll wonder why you |
| 48 | +ever tolerated `useEffect`. |
| 49 | + |
| 50 | +’’’’’ |
| 51 | + |
| 52 | +## Getting Started |
| 53 | + |
| 54 | +``` bash |
| 55 | +# Clone the repository |
| 56 | +git clone https://github.com/hyperpolymath/panll.git |
| 57 | +cd panll |
| 58 | + |
| 59 | +# Using Nix (recommended for reproducibility) |
| 60 | +nix develop |
| 61 | + |
| 62 | +# Or using toolbox/distrobox |
| 63 | +toolbox create panll-dev |
| 64 | +toolbox enter panll-dev |
| 65 | +# Install dependencies manually |
| 66 | + |
| 67 | +# Verify setup |
| 68 | +just check # or: cargo check / mix compile / etc. |
| 69 | +just test # Run test suite |
| 70 | +``` |
| 71 | + |
| 72 | +### Repository Structure |
| 73 | + |
| 74 | + panll/ |
| 75 | + ├── src/ # Source code (Perimeter 1-2) |
| 76 | + ├── lib/ # Library code (Perimeter 1-2) |
| 77 | + ├── extensions/ # Extensions (Perimeter 2) |
| 78 | + ├── plugins/ # Plugins (Perimeter 2) |
| 79 | + ├── tools/ # Tooling (Perimeter 2) |
| 80 | + ├── docs/ # Documentation (Perimeter 3) |
| 81 | + │ ├── architecture/ # ADRs, specs (Perimeter 2) |
| 82 | + │ └── proposals/ # RFCs (Perimeter 3) |
| 83 | + ├── examples/ # Examples (Perimeter 3) |
| 84 | + ├── spec/ # Spec tests (Perimeter 3) |
| 85 | + ├── tests/ # Test suite (Perimeter 2-3) |
| 86 | + ├── .well-known/ # Protocol files (Perimeter 1-3) |
| 87 | + ├── .github/ # GitHub config (Perimeter 1) |
| 88 | + │ ├── ISSUE_TEMPLATE/ |
| 89 | + │ └── workflows/ |
| 90 | + ├── CHANGELOG.md |
| 91 | + ├── CODE_OF_CONDUCT.md |
| 92 | + ├── CONTRIBUTING.md # This file |
| 93 | + ├── GOVERNANCE.md |
| 94 | + ├── LICENSE |
| 95 | + ├── MAINTAINERS.md |
| 96 | + ├── README.adoc |
| 97 | + ├── SECURITY.md |
| 98 | + ├── flake.nix # Nix flake (Perimeter 1) |
| 99 | + └── Justfile # Task runner (Perimeter 1) |
| 100 | + |
| 101 | +’’’’’ |
| 102 | + |
| 103 | +## How to Contribute |
| 104 | + |
| 105 | +### Reporting Bugs |
| 106 | + |
| 107 | +**Before reporting**: 1. Search existing issues 2. Check if it’s already |
| 108 | +fixed in `main` 3. Determine which perimeter the bug affects |
| 109 | + |
| 110 | +**When reporting**: |
| 111 | + |
| 112 | +Use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.md) and |
| 113 | +include: |
| 114 | + |
| 115 | +- Clear, descriptive title |
| 116 | + |
| 117 | +- Environment details (OS, versions, toolchain) |
| 118 | + |
| 119 | +- Steps to reproduce |
| 120 | + |
| 121 | +- Expected vs actual behaviour |
| 122 | + |
| 123 | +- Logs, screenshots, or minimal reproduction |
| 124 | + |
| 125 | +### Suggesting Features |
| 126 | + |
| 127 | +**Before suggesting**: 1. Check the [roadmap](ROADMAP.md) if available |
| 128 | +2. Search existing issues and discussions 3. Consider which perimeter |
| 129 | +the feature belongs to |
| 130 | + |
| 131 | +**When suggesting**: |
| 132 | + |
| 133 | +Use the [feature request |
| 134 | +template](.github/ISSUE_TEMPLATE/feature_request.md) and include: |
| 135 | + |
| 136 | +- Problem statement (what pain point does this solve?) |
| 137 | + |
| 138 | +- Proposed solution |
| 139 | + |
| 140 | +- Alternatives considered |
| 141 | + |
| 142 | +- Which perimeter this affects |
| 143 | + |
| 144 | +### Your First Contribution |
| 145 | + |
| 146 | +Look for issues labelled: |
| 147 | + |
| 148 | +- [`good` `first` |
| 149 | + `issue`](https://github.com/hyperpolymath/panll/labels/good%20first%20issue) |
| 150 | + — Simple Perimeter 3 tasks |
| 151 | + |
| 152 | +- [`help` |
| 153 | + `wanted`](https://github.com/hyperpolymath/panll/labels/help%20wanted) |
| 154 | + — Community help needed |
| 155 | + |
| 156 | +- [`documentation`](https://github.com/hyperpolymath/panll/labels/documentation) |
| 157 | + — Docs improvements |
| 158 | + |
| 159 | +- [`perimeter-3`](https://github.com/hyperpolymath/panll/labels/perimeter-3) |
| 160 | + — Community sandbox scope |
| 161 | + |
| 162 | +’’’’’ |
| 163 | + |
| 164 | +## Development Workflow |
| 165 | + |
| 166 | +### Branch Naming |
| 167 | + |
| 168 | + docs/short-description # Documentation (P3) |
| 169 | + test/what-added # Test additions (P3) |
| 170 | + feat/short-description # New features (P2) |
| 171 | + fix/issue-number-description # Bug fixes (P2) |
| 172 | + refactor/what-changed # Code improvements (P2) |
| 173 | + security/what-fixed # Security fixes (P1-2) |
| 174 | + |
| 175 | +### Commit Messages |
| 176 | + |
| 177 | +We follow [Conventional Commits](https://www.conventionalcommits.org/): |
| 178 | +\`\`\` (): |
| 179 | + |
| 180 | +\[optional body\] |
| 181 | + |
| 182 | +\[optional footer\] |
0 commit comments