Files
periscope/docs/development/CODING_CONSTITUTION.md
T
michele 0533d4ebd2 Add Periscope Cursor engineering constitution and always-on rules.
Docs-only: master CODING_CONSTITUTION plus seven .mdc splits. Git policy is
phase = test then commit+push; deploy only after a macro-phase.
2026-09-20 18:06:00 +02:00

91 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Periscope Cursor Engineering Rules
Mandatory for every Cursor agent working on Periscope. Do not invent a weaker local policy. This file is the master; `.cursor/rules/*.mdc` split the same text by section and must not contradict it.
## 0. Coding constitution
- You are implementing Periscope (schematic/PCB validation), not a generic scaffold and not Faradworks/PinScope under a new name.
- Prefer original Periscope source in `periscope/src` over copying PinScope. Overlay stamps, `cp` of `periscope/dependency/**`, and near-identical pastes do **not** create architectural or AGPL independence.
- Keep `periscope/dependency/` until a rewritten slice is proven. Never empty-delete inherited files to “look native.”
- Auto-place / pcbnew write-back is out of scope unless Michele explicitly asks.
- Never touch live auth users, password hashes, or `AUTH_JWT_SECRET` unless Michele explicitly orders a credential change in that turn.
- Never swallow exceptions with bare `except: continue`. Log or re-raise.
- Match existing public contracts (Pydantic models, REST shapes, finding engine). Frontend types stay in sync with backend models.
- AGPL-3.0 of the fork stays visible. Do not relicense. Do not detach the GitHub fork unless Michele and counsel say so.
- Gateway-owned seams stay stub-shaped (`billing_hook.get_billing()`, frontend auth/billing pass-throughs). Do not import Clerk/Stripe SDKs outside those seams.
- Skills stay local (`skills/*/SKILL.md` + `validate.py` on DeepSeek). Do not run `scripts/upload_skills.py`.
- Default LLM path is DeepSeek. Do not route live stages to Anthropic Console.
## 1. Architecture
Three layers:
| Layer | Location | Purpose |
| --- | --- | --- |
| Core | `backend/periscopex/` (native under `periscope/src` when split) | Models, parsers, graph, validator, passives, taxonomy, derating |
| Backend | `backend/` | FastAPI, pipeline, SSE, storage |
| Frontend | `frontend/` | Next.js app: dashboard, progress, report, derating, admin |
Physical split (when present): `periscope/src` = Periscope; `periscope/dependency` = inherited PinScope in-tree. Docker copies dependency then src so native files win **only when they are real replacements**, not stamped copies.
Import switch rule: keep calling `dependency/` until pytest + deploy smoke pass for that slice, then switch imports. Fail-soft: if verification fails, leave the inherited path.
Netlist is a queryable bipartite graph (components + nets). Deterministic checks beat heuristics. Finding normalization is downgrade-only. Cross-IC excerpt budget is global plus per-neighbor.
Content-addressed datasheets live under `library/datasheets/`. DigiKey matches exact MPN only. Value-string passives stay per-project, never the shared library.
Do not add auth, billing, or extra services unless the task needs them. Do not add a second frontend component library.
## 2. Python
- Python 3.12+, Pydantic 2.x, FastAPI on the backend.
- Parsers and graph builders are pure functions without hidden I/O, except documented loaders (`build_graph` from paths).
- All shared data structures are Pydantic models in `backend/periscopex/models.py` (or the native successor once rewritten).
- Tests live under `tests/` against `simple_project/` as ground truth. Emmaforo behavior is a live spec, not a license to skip unit tests.
- Extraction prompts live in `skills/` and run in-process. Bump `default_model_version` in `skills_manifest.json` when skill prompts change; never call Anthropic Console.
- Use stdlib hashing (`hashlib.scrypt` in `local_users.hash_password`) for local passwords. Do not invent a homemade hash.
- `repo_paths.py` locates taxonomy, skills, vendor, changelog. Do not hard-code `/app` without the Docker heuristic that also requires `vendor/`.
- Format and lint with the repos existing tools. Do not drive-by reformat unrelated files.
## 3. Rust
- Periscopes product code is Python/TypeScript today. If a Rust crate is added, it is original Periscope code, not a paste of an AGPL PinScope module.
- Rust slices follow the same verify-then-switch rule: tests first, then wire into the Python/TS surface.
- Use `rustfmt` + `clippy` on that crate. No `unsafe` without a comment that names the invariant.
- Do not introduce Rust to dodge AGPL or to empty-delete Python in `dependency/`.
## 4. Testing
- Write tests before considering a slice done. Prefer tests that lock behavior (graph topology, finding codes, via≠pad, review isolation) over tests that assert overlay stamps or file provenance comments.
- `pytest` from the worktree with the project venv. Do not claim green from a system Python missing deps.
- One malformed IC must not kill the whole review; keep per-IC isolation tests.
- Do not add tests whose only job is to require `Native Periscope overlay` in a copied file.
- UI changes: exercise the flow (not a single screenshot). If no browser tools, say what was not verified.
- Installing docs/rules is a docs phase: existence and internal consistency of the seven `.mdc` files plus this master is the check. There is no product pytest gate for markdown-only.
## 5. Verification
- Verify-then-switch: pytest (or the docs check above) **then** import/path switch, **then** commit+push at phase end.
- Live smoke after a **macro-phase** deploy: version from changelog, health of `/api/auth/mode`, overlay/rewrite modules that should load, users **untouched**.
- Deploy script: `/root/periscope` `./scripts/update-periscope.sh`. Prefer `--no-pull` after the host checkout is already on the intended SHA. Do not let the script generate a new `AUTH_JWT_SECRET` if one exists.
- Do not treat Docker COPY of `src` over `dependency` as proof of a rewrite.
## 6. Git workflow
Worktree for this product line: `~/Development/pinscope-tree-split` unless Michele names another. Do not start a second clone to dodge the worktree.
### Phase vs macro-phase
- **Phase** (one verified slice: e.g. rules install, one rewritten module with tests): when tests (or the docs check) pass → **commit and push**. That is the end of the phase.
- **Macro-phase** (a named batch of phases Michele treats as one shippable increment): **deploy only after a macro-phase**, not after every phase, and not at a mere phase boundary.
- **No commit, push, or deploy on every small edit.** Edit, keep working, commit when the phase is actually done.
- **No deploy at a mere phase boundary.** Passing tests + push is not a deploy order.
### Other git rules
- Feature branches `cursor/<descriptive-name>-0d9d` (lowercase). Do not force-push unless Michele explicitly orders it.
- Do not create pull requests unless Michele asks.
- Push `origin` and `github` when this worktree has both remotes.
- Do not commit secrets, `data/auth/users`, or `.env` password material.
- Changelog version is the latest `## x.y.z` in `frontend/content/changelog.md` (dependency copy is the Docker source of truth today). Bump only when the phase is a product change, not for docs-only rules unless Michele wants a version bump.